diff --git a/whitelist/apichanges.xml b/whitelist/apichanges.xml new file mode 100644 --- /dev/null +++ b/whitelist/apichanges.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + White List API + + + + + + + + Added WhiteListQuery to check violations of runtime restrictions + + + + + +

+ Added WhiteListQuery to check violations of runtime restrictions. The project types supporting a runtime + with class usage restriction implement the WhiteListQueryImplementation to provide a white list + of allowed types (methods). +

+
+ + + +
+
+ + + + + + + White List API changes by date + + + + + + +

Introduction

+ +

This document lists changes made to the White List APIs. Please ask on the +dev@java.netbeans.org or nbdev@netbeans.org +mailing list if you have any questions about the details of a +change, or are wondering how to convert existing code to be compatible.

+ +
+ +

@FOOTER@

+ + +
+
diff --git a/whitelist/build.xml b/whitelist/build.xml new file mode 100644 --- /dev/null +++ b/whitelist/build.xml @@ -0,0 +1,5 @@ + + + Builds, tests, and runs the project org.netbeans.modules.whitelist + + diff --git a/whitelist/manifest.mf b/whitelist/manifest.mf new file mode 100644 --- /dev/null +++ b/whitelist/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: org.netbeans.modules.whitelist +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/whitelist/Bundle.properties +OpenIDE-Module-Layer: org/netbeans/modules/whitelist/resources/layer.xml +OpenIDE-Module-Specification-Version: 1.0 + diff --git a/whitelist/nbproject/project.properties b/whitelist/nbproject/project.properties new file mode 100644 --- /dev/null +++ b/whitelist/nbproject/project.properties @@ -0,0 +1,5 @@ +is.autoload=true +javac.source=1.6 +javac.compilerargs=-Xlint -Xlint:-serial +javadoc.apichanges=${basedir}/apichanges.xml + diff --git a/whitelist/nbproject/project.xml b/whitelist/nbproject/project.xml new file mode 100644 --- /dev/null +++ b/whitelist/nbproject/project.xml @@ -0,0 +1,88 @@ + + + org.netbeans.modules.apisupport.project + + + org.netbeans.modules.whitelist + + + org.netbeans.api.annotations.common + + + + 1 + 1.10 + + + + org.netbeans.libs.javacapi + + + + 7.7 + + + + org.netbeans.modules.java.source + + + + 0.84 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.37 + + + + org.netbeans.modules.projectuiapi + + + + 1 + 1.52 + + + + org.openide.filesystems + + + + 7.49 + + + + org.openide.util + + + + 8.16 + + + + org.openide.util.lookup + + + + 8.10 + + + + + org.netbeans.modules.j2ee.weblogic9 + org.netbeans.modules.java.editor + org.netbeans.modules.web.project + org.netbeans.api.whitelist + org.netbeans.spi.whitelist + org.netbeans.spi.whitelist.support + + + + diff --git a/whitelist/src/org/netbeans/api/whitelist/WhiteListQuery.java b/whitelist/src/org/netbeans/api/whitelist/WhiteListQuery.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/api/whitelist/WhiteListQuery.java @@ -0,0 +1,200 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.api.whitelist; + +import javax.swing.event.ChangeListener; +import org.netbeans.api.annotations.common.CheckForNull; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.java.source.ElementHandle; +import org.netbeans.api.project.Project; +import org.netbeans.modules.whitelist.project.WhiteListCategoryPanel; +import org.netbeans.spi.whitelist.WhiteListQueryImplementation; +import org.netbeans.spi.whitelist.WhiteListQueryImplementation.WhiteListImplementation; +import org.openide.filesystems.FileObject; +import org.openide.util.Lookup; +import org.openide.util.Parameters; + +/** + * Query for finding white lists used to emit errors for usages of non allowed + * types or methods. The project types supporting a runtime with class usage + * restriction implement the {@link WhiteListQueryImplementation} to provide a + * white list of allowed types (methods). + * @author Tomas Zezula + * @author David Konecny + */ +public final class WhiteListQuery { + + private static final Lookup.Result queries = + Lookup.getDefault().lookupResult(WhiteListQueryImplementation.class); + + private WhiteListQuery(){} + + /** + * Returns a white list for given file. + * @param file the file for which the white list should be obtained. + * @return the {@link WhiteList} for given file or null if no white list + * is associated with given file. + */ + @CheckForNull + public static WhiteList getWhiteList(@NonNull final FileObject file) { + Parameters.notNull("file", file); //NOI18N + for (WhiteListQueryImplementation query : queries.allInstances()) { + final WhiteListImplementation whiteListImpl = query.getWhiteList(file); + if (whiteListImpl != null) { + return new WhiteList(whiteListImpl); + } + } + return null; + } + + /** + * Enables the given white list in the project. + * At the moment assumption is that if a project want to automatically enable + * some white list then they likely know whitelistId. + * @param project the project in which the white list should be enabled + * @param whiteListId the white list identifier + * @param enable if true the white list is enabled if false white list is disabled + */ + public static void enableWhiteListInProject(@NonNull Project project, @NonNull String whiteListId, boolean enable) { + WhiteListCategoryPanel.enableWhiteListInProject(project, whiteListId, enable); + } + + /** + * The white list used to emit errors for usages of non allowed + * types or methods. + */ + public static final class WhiteList { + + private final WhiteListImplementation impl; + + private WhiteList( + @NonNull final WhiteListImplementation impl) { + Parameters.notNull("impl", impl); //NOI18N + this.impl = impl; + } + + /** + * Checks if given method (type) can be invoked (accessed). + * @param element to check + * @param operation the operation which should be tested + * @return a {@link Result} holding the details. + */ + public final Result check( + @NonNull final ElementHandle element, + @NonNull final Operation operation) { + Parameters.notNull("element", element); //NOI18N; + Parameters.notNull("operation", operation); //NOI18N; + return impl.check(element, operation); + } + + /** + * Adds {@link ChangeListener} to white list. The listener is + * notified when the white list is changed. + * @param listener to be added + */ + public void addChangeListener(@NonNull final ChangeListener listener) { + Parameters.notNull("listener", listener); //NOI18N + impl.addChangeListener(listener); + } + + /** + * Removes {@link ChangeListener} from white list. + * @param listener to be removed + */ + public void removeChangeListener(@NonNull final ChangeListener listener) { + Parameters.notNull("listener", listener); //NOI18N + impl.removeChangeListener(listener); + } + } + + /** + * Operation on element to be tested (usage, subclassing) + */ + public enum Operation { + /** + * Checks the white list if usage of given element is supported. + */ + USAGE + } + + /** + * Result of the white list check. + */ + public static final class Result { + private final boolean allowed; + private final String violatedRuleName; + private final String violatedRuleDescription; + + //Todo: Make private + public Result(boolean allowed, String violatedRuleName, String violatedRuleDescription) { + this.allowed = allowed; + this.violatedRuleName = violatedRuleName; + this.violatedRuleDescription = violatedRuleDescription; + } + + /** + * Returns true if the operation on given element is allowed by white list. + * @return true if the operation on given element is allowed + */ + public boolean isAllowed() { + return allowed; + } + + /** + * Returns description of violated rule if {@link WhiteListQuery.Result#isAllowed} + * returned false otherwise returns null. + * @return the description of violated rule. + */ + public String getViolatedRuleDescription() { + return violatedRuleDescription; + } + + /** + * Returns name of violated rule if {@link WhiteListQuery.Result#isAllowed} + * returned false otherwise returns null. + * @return the name of violated rule. + */ + public String getViolatedRuleName() { + return violatedRuleName; + } + } +} diff --git a/whitelist/src/org/netbeans/modules/whitelist/Bundle.properties b/whitelist/src/org/netbeans/modules/whitelist/Bundle.properties new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/modules/whitelist/Bundle.properties @@ -0,0 +1,2 @@ +OpenIDE-Module-Display-Category=Java +OpenIDE-Module-Name=Whitelist Support diff --git a/whitelist/src/org/netbeans/modules/whitelist/ProjectWhiteListQueryImpl.java b/whitelist/src/org/netbeans/modules/whitelist/ProjectWhiteListQueryImpl.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/modules/whitelist/ProjectWhiteListQueryImpl.java @@ -0,0 +1,67 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.whitelist; + +import org.netbeans.api.project.FileOwnerQuery; +import org.netbeans.api.project.Project; +import org.netbeans.spi.whitelist.WhiteListQueryImplementation; +import org.openide.filesystems.FileObject; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author Tomas Zezula + */ +@ServiceProvider(service=WhiteListQueryImplementation.class, position=100) +public class ProjectWhiteListQueryImpl implements WhiteListQueryImplementation { + @Override + public WhiteListImplementation getWhiteList(FileObject file) { + final Project project = FileOwnerQuery.getOwner(file); + if (project != null) { + final WhiteListQueryImplementation delegate = project.getLookup().lookup(WhiteListQueryImplementation.class); + if (delegate != null) { + return delegate.getWhiteList(file); + } + } + return null; + } +} diff --git a/whitelist/src/org/netbeans/modules/whitelist/project/Bundle.properties b/whitelist/src/org/netbeans/modules/whitelist/project/Bundle.properties new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/modules/whitelist/project/Bundle.properties @@ -0,0 +1,3 @@ +WhiteListCategoryPanel.jLabel1.text=Active whitelists: +LBL_CategoryWhitelist=Whitelists +WhiteListCategoryPanel.jLabel2.text=Note: This project has been used in context of enteprise application which runtime container is constrained by above Whitelists. diff --git a/whitelist/src/org/netbeans/modules/whitelist/project/WhiteListCategoryPanel.form b/whitelist/src/org/netbeans/modules/whitelist/project/WhiteListCategoryPanel.form new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/modules/whitelist/project/WhiteListCategoryPanel.form @@ -0,0 +1,66 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/whitelist/src/org/netbeans/modules/whitelist/project/WhiteListCategoryPanel.java b/whitelist/src/org/netbeans/modules/whitelist/project/WhiteListCategoryPanel.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/modules/whitelist/project/WhiteListCategoryPanel.java @@ -0,0 +1,336 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ + +/* + * WhiteListCategoryPanel.java + * + * Created on 22/07/2011, 7:37:04 AM + */ +package org.netbeans.modules.whitelist.project; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.prefs.Preferences; +import javax.swing.DefaultCellEditor; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.api.project.ProjectUtils; +import org.netbeans.api.whitelist.WhiteListQuery; +import org.netbeans.spi.project.ui.support.ProjectCustomizer; +import org.netbeans.spi.whitelist.WhiteListQueryImplementation; +import org.netbeans.spi.whitelist.WhiteListQueryImplementation.UserSelectable; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; + +/** + * + * @author david + */ +public class WhiteListCategoryPanel extends javax.swing.JPanel implements ActionListener { + + private static final String WHITELISTS_PATH = "org-netbeans-api-java/whitelists/"; //NOI18N + + private static Map> lookupCache = + new WeakHashMap>(); + + private Project p; + + /** Creates new form WhiteListCategoryPanel */ + public WhiteListCategoryPanel(Project p) { + this.p = p; + initComponents(); + WhiteListsModel model = new WhiteListsModel(getTableContent()); + jTable1.setModel(model); + jTable1.getTableHeader().setVisible(false); + jTable1.getTableHeader().setPreferredSize(new Dimension(0, 0)); + jTable1.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(new JCheckBox())); + jTable1.getColumnModel().getColumn(0).setMaxWidth(25); + jTable1.getColumnModel().getColumn(0).setMinWidth(25); + } + + private List getTableContent() { + List l = new ArrayList(); + for (WhiteListQueryImplementation.UserSelectable impl : getUserSelectableWhiteLists()) { + l.add(new Desc(impl, isWhiteListEnabledInProject(p, impl.getId()))); + } + return l; + } + + public static ProjectCustomizer.CompositeCategoryProvider createWhiteListCategoryProvider(Map attrs) { + return new Factory(); //NOI18N + } + + @Override + public void actionPerformed(ActionEvent e) { + for (Desc d : ((WhiteListsModel)jTable1.getModel()).whitelists) { + enableWhiteListInProject(p, d.w.getId(), d.active); + } + } + + public static class Factory implements ProjectCustomizer.CompositeCategoryProvider { + + private static final String CATEGORY_WHITELIST = "WhiteList"; // NOI18N + + public Factory() { + } + + public ProjectCustomizer.Category createCategory(Lookup context) { + Project p = context.lookup(Project.class); + if (p == null) { + return null; + } + if (!isWhiteListPanelEnabled(p) || getUserSelectableWhiteLists().size() == 0) { + return null; + } + return ProjectCustomizer.Category.create( + CATEGORY_WHITELIST, + NbBundle.getMessage(WhiteListCategoryPanel.class, "LBL_CategoryWhitelist"), //NOI18N + null); + } + + public JComponent createComponent(ProjectCustomizer.Category category, Lookup context) { + Project p = context.lookup(Project.class); + assert p != null; + WhiteListCategoryPanel customizerPanel = new WhiteListCategoryPanel(p); + category.setStoreListener(customizerPanel); + return customizerPanel; + } + } // End of Factory class + + public static final String PROP_WHITELIST_ENABLED = "whitelist-enabled"; + public static final String PROP_WHITELIST = "whitelist-"; + + public static boolean isWhiteListPanelEnabled(@NonNull Project p) { + Preferences prefs = ProjectUtils.getPreferences(p, WhiteListQuery.class, true); + return prefs.getBoolean(PROP_WHITELIST_ENABLED, false); + } + + public static boolean isWhiteListEnabledInProject(@NonNull Project p, @NonNull String whiteListId) { + Preferences prefs = ProjectUtils.getPreferences(p, WhiteListQuery.class, true); + return prefs.getBoolean(PROP_WHITELIST+whiteListId, false); + } + + public static void enableWhiteListInProject(@NonNull Project p, final @NonNull String whiteListId, final boolean enable) { + final Preferences prefs = ProjectUtils.getPreferences(p, WhiteListQuery.class, true); + ProjectManager.mutex().writeAccess(new Runnable() { + @Override + public void run() { + prefs.putBoolean(PROP_WHITELIST+whiteListId, enable); + if (enable) { + prefs.putBoolean(PROP_WHITELIST_ENABLED, true); + } + } + }); + synchronized (WhiteListCategoryPanel.class) { + final Reference lkpRef = lookupCache.get(p); + final WhiteListLookup lkp; + if (lkpRef != null && (lkp=lkpRef.get())!=null) { + lkp.updateLookup(p); + } + } + } + + public static Collection getUserSelectableWhiteLists() { + return Lookups.forPath(WHITELISTS_PATH).lookupResult(WhiteListQueryImplementation.UserSelectable.class).allInstances(); + } + + public static Lookup getEnabledUserSelectableWhiteLists(@NonNull Project p) { + Reference lkpRef = lookupCache.get(p); + WhiteListLookup lkp; + if (lkpRef == null || (lkp=lkpRef.get())==null) { + lkp = new WhiteListLookup(); + lkp.updateLookup(p); + lookupCache.put(p,new WeakReference(lkp)); + } + return lkp; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTable1 = new javax.swing.JTable(); + jLabel2 = new javax.swing.JLabel(); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(WhiteListCategoryPanel.class, "WhiteListCategoryPanel.jLabel1.text")); // NOI18N + + jScrollPane1.setViewportView(jTable1); + + jLabel2.setText(org.openide.util.NbBundle.getMessage(WhiteListCategoryPanel.class, "WhiteListCategoryPanel.jLabel2.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addContainerGap(283, Short.MAX_VALUE)) + .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 233, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTable jTable1; + // End of variables declaration//GEN-END:variables + + private static class Desc { + private WhiteListQueryImplementation.UserSelectable w; + private boolean active; + + public Desc(UserSelectable w, boolean active) { + this.w = w; + this.active = active; + } + } + + private static class WhiteListsModel implements TableModel { + + private List whitelists; + + public WhiteListsModel(List whitelists) { + assert whitelists.size() > 0; + this.whitelists = new ArrayList(whitelists); + } + + @Override + public int getRowCount() { + return whitelists.size(); + } + + @Override + public int getColumnCount() { + return 2; + } + + private String[] header = new String[]{"Enabled", "Whitelist"}; + private Class[] headerClass = new Class[]{Boolean.class, String.class}; + + @Override + public String getColumnName(int columnIndex) { + return header[columnIndex]; + } + + @Override + public Class getColumnClass(int columnIndex) { + return headerClass[columnIndex]; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex == 0; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + Desc srd = whitelists.get(rowIndex); + if (columnIndex == 0) { + return Boolean.valueOf(srd.active); + } else { + return srd.w.getDisplayName(); + } + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + if (aValue instanceof Boolean) { + whitelists.get(rowIndex).active = ((Boolean)aValue).booleanValue(); + } + } + + @Override + public void addTableModelListener(TableModelListener l) { + } + + @Override + public void removeTableModelListener(TableModelListener l) { + } + + } + + private static class WhiteListLookup extends ProxyLookup { + + public void updateLookup(final Project p) { + final List impls = new ArrayList(); + for (WhiteListQueryImplementation.UserSelectable w : + Lookups.forPath(WHITELISTS_PATH).lookupAll(WhiteListQueryImplementation.UserSelectable.class)) { + if (WhiteListCategoryPanel.isWhiteListEnabledInProject(p, w.getId())) { + impls.add(w); + } + } + setLookups(Lookups.fixed((UserSelectable[])impls.toArray(new UserSelectable[impls.size()]))); + } + } +} diff --git a/whitelist/src/org/netbeans/modules/whitelist/project/WhiteListLookupProvider.java b/whitelist/src/org/netbeans/modules/whitelist/project/WhiteListLookupProvider.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/modules/whitelist/project/WhiteListLookupProvider.java @@ -0,0 +1,60 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.whitelist.project; + +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.LookupProvider; +import org.openide.util.Lookup; + +/** + * + */ +public class WhiteListLookupProvider implements LookupProvider { + + + @Override + public Lookup createAdditionalLookup(Lookup baseContext) { + Project p = baseContext.lookup(Project.class); + assert p != null; + return WhiteListCategoryPanel.getEnabledUserSelectableWhiteLists(p); + } +} diff --git a/whitelist/src/org/netbeans/modules/whitelist/resources/layer.xml b/whitelist/src/org/netbeans/modules/whitelist/resources/layer.xml new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/modules/whitelist/resources/layer.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/whitelist/src/org/netbeans/spi/whitelist/WhiteListQueryImplementation.java b/whitelist/src/org/netbeans/spi/whitelist/WhiteListQueryImplementation.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/spi/whitelist/WhiteListQueryImplementation.java @@ -0,0 +1,104 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.spi.whitelist; + +import javax.swing.event.ChangeListener; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.java.source.ElementHandle; +import org.netbeans.api.whitelist.WhiteListQuery; +import org.openide.filesystems.FileObject; + +/** + * Permits projects to provide wite list used to emit errors for usages of non allowed + * types or methods. The project types supporting a runtime with class usage + * restriction implement this interface to provide a white list of allowed types (methods). + * @author Tomas Zezula + * @author David Konecny + */ +public interface WhiteListQueryImplementation { + + /** + * Returns a white list for given file. + * @param file to return white list for. + * @return the {@link WhiteListImplementation} for given file. + */ + WhiteListImplementation getWhiteList( + @NonNull FileObject file); + + /** + * All white lists which should be displayed in UI for user should implement + * this interface. And on the other hand non-visible implementations like + * for example merging WhiteListQueryImplementation should not implement it. + */ + public interface UserSelectable extends WhiteListQueryImplementation { + String getDisplayName(); + String getId(); + } + + /** + * The white list implementation used to emit errors for usages of non allowed + * types or methods. + */ + public interface WhiteListImplementation { + + /** + * Checks if given method (type) can be invoked (accessed). + * @param element to check + * @param operation the operation which should be tested + * @return a {@link Result} holding the details. + */ + WhiteListQuery.Result check(@NonNull ElementHandle element, @NonNull WhiteListQuery.Operation operation); + + /** + * Adds {@link ChangeListener} to white list. + * @param listener to be added + */ + void addChangeListener(@NonNull final ChangeListener listener); + + /** + * Removes {@link ChangeListener} from white list. + * @param listener to be removed + */ + void removeChangeListener(@NonNull final ChangeListener listener); + } + +} diff --git a/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListQueryMergerSupport.java b/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListQueryMergerSupport.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListQueryMergerSupport.java @@ -0,0 +1,199 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.spi.whitelist.support; + +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.WeakHashMap; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.java.source.ElementHandle; +import org.netbeans.api.whitelist.WhiteListQuery; +import org.netbeans.spi.whitelist.WhiteListQueryImplementation; +import org.netbeans.spi.whitelist.WhiteListQueryImplementation.WhiteListImplementation; +import org.netbeans.spi.project.LookupMerger; +import org.openide.filesystems.FileObject; +import org.openide.util.ChangeSupport; +import org.openide.util.Lookup; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.WeakListeners; + +/** + * Support for writing {@link WhiteListQueryImplementation}. + * @author David Konecny + * @author Tomas Zezula + */ +public class WhiteListQueryMergerSupport { + + /** + * Placed in a lookup this class will merge all other WhiteListQueryImplementation + * registered in the same lookup. All individual WhiteListQueryImplementation must + * allow invocation and/or overriding of a method to get positive return. + */ + public static LookupMerger createWhiteListQueryMerger() { + return new WhiteListQueryMerger(); + } + + private static class WhiteListQueryMerger implements LookupMerger { + + public Class getMergeableClass() { + return WhiteListQueryImplementation.class; + } + + public WhiteListQueryImplementation merge(Lookup lookup) { + return new WhiteListQueryImplementationMerged(lookup); + } + } + + private static class WhiteListQueryImplementationMerged implements WhiteListQueryImplementation { + private Lookup lkp; + private final Map> canonicalCache; + + public WhiteListQueryImplementationMerged(Lookup lkp) { + this.lkp = lkp; + this.canonicalCache = new WeakHashMap>(); + } + + @Override + public synchronized WhiteListImplementation getWhiteList(final FileObject file) { + final Reference ref = canonicalCache.get(file); + WhiteListImplementation wl = ref == null ? null : ref.get(); + if (wl != null) { + return wl; + } + final Lookup.Result lr = lkp.lookupResult(WhiteListQueryImplementation.class); + boolean empty = true; + for (WhiteListQueryImplementation impl : lr.allInstances()) { + WhiteListImplementation i = impl.getWhiteList(file); + if (i != null) { + empty = false; + break; + } + } + if (empty) { + return null; + } + wl = new WhiteListImplementationMerged(lr,file); + canonicalCache.put(file,new WeakReference(wl)); + return wl; + } + } + + private static class WhiteListImplementationMerged implements WhiteListImplementation, ChangeListener, LookupListener { + + private final Lookup.Result lr; + private final FileObject file; + private final ChangeSupport changeSupport; + //@GuardedBy("this") + private Map cache; + + @SuppressWarnings("LeakingThisInConstructor") + public WhiteListImplementationMerged( + @NonNull final Lookup.Result lr, + @NonNull final FileObject file) { + this.lr = lr; + this.file = file; + this.changeSupport = new ChangeSupport(this); + this.lr.addLookupListener(WeakListeners.create(LookupListener.class, this, this.lr)); + } + + @Override + @NonNull + public WhiteListQuery.Result check( + @NonNull final ElementHandle element, + @NonNull final WhiteListQuery.Operation operation) { + for (WhiteListImplementation impl : getWhiteLists()) { + WhiteListQuery.Result r = impl.check(element, operation); + if (r != null) { + return r; + } + } + return null; + } + + @Override + public void addChangeListener(@NonNull final ChangeListener listener) { + this.changeSupport.addChangeListener(listener); + } + + @Override + public void removeChangeListener(@NonNull final ChangeListener listener) { + this.changeSupport.removeChangeListener(listener); + } + + @Override + public void stateChanged(final ChangeEvent event) { + this.changeSupport.fireChange(); + } + + @Override + public void resultChanged(LookupEvent ev) { + this.changeSupport.fireChange(); + } + + private Iterable getWhiteLists() { + synchronized (this) { + if (cache != null) { + return cache.keySet(); + } + } + final Map map = new IdentityHashMap(); + for (WhiteListQueryImplementation wlq : lr.allInstances()) { + final WhiteListImplementation wl = wlq.getWhiteList(file); + final ChangeListener cl = WeakListeners.change(this, wl); + wl.addChangeListener(cl); + map.put(wl, cl); + } + synchronized (this) { + if (cache == null) { + cache = map; + } + return cache.keySet(); + } + } + } + +}