EXTSCRIPT-154: Code Rewrite/Refactoring, adding annotation processing
git-svn-id: https://svn.apache.org/repos/asf/myfaces/extensions/scripting/trunk@1299647 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/api/AnnotationScanListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/api/AnnotationScanListener.java
new file mode 100644
index 0000000..9decb8e
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/api/AnnotationScanListener.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.core.api;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ * <p/>
+ * We use a source code artifact observer here to register the
+ * meta data in the correct registry entries
+ */
+
+public interface AnnotationScanListener extends ClassScanListener
+{
+
+ /**
+ * returns true if the annotation marked by the incoming parameter is supported by this scanner
+ *
+ * @param annotation the supported annotation as neutral string representation of its class
+ * @return in case of support
+ */
+ public boolean supportsAnnotation(String annotation);
+
+ /**
+ * returns true if the annotation marked by the incoming parameter is supported by this scanner
+ *
+ * @param annotation the supported annotation as neutral string representation of its class
+ * @return in case of support
+ */
+ public boolean supportsAnnotation(Class annotation);
+
+
+ /**
+ * Class file registration of the supported annotation
+ *
+ * @param clazz the class to be registered
+ * @param annotationName the annotation for the class
+ */
+ public void register(Class clazz, Annotation annotationName);
+
+ /**
+ * Purges the class from the correct places of the myfaces registry
+ * so that the artifact is not reachable anymore
+ *
+ * @param className the class name for the class which needs to be purged
+ */
+ public void purge(String className);
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/api/ClassScanListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/api/ClassScanListener.java
new file mode 100644
index 0000000..1eab14b
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/api/ClassScanListener.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.core.api;
+
+/**
+ * Observer interface which will be the base
+ * of a future event system
+ * (note currently unused)
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+public interface ClassScanListener {
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/context/WeavingContext.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/context/WeavingContext.java
index 4984cdc..a2b965a 100644
--- a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/context/WeavingContext.java
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/core/context/WeavingContext.java
@@ -19,12 +19,10 @@
package rewrite.org.apache.myfaces.extensions.scripting.core.context;
-import org.apache.myfaces.extensions.scripting.core.dependencyScan.core.ClassDependencies;
-import rewrite.org.apache.myfaces.extensions.scripting.core.loader.ThrowAwayClassloader;
-
import rewrite.org.apache.myfaces.extensions.scripting.core.common.Decorated;
import rewrite.org.apache.myfaces.extensions.scripting.core.engine.FactoryEngines;
import rewrite.org.apache.myfaces.extensions.scripting.core.engine.api.ScriptingEngine;
+import rewrite.org.apache.myfaces.extensions.scripting.core.loader.ThrowAwayClassloader;
import rewrite.org.apache.myfaces.extensions.scripting.core.monitor.ClassResource;
import rewrite.org.apache.myfaces.extensions.scripting.core.monitor.WatchedResource;
import rewrite.org.apache.myfaces.extensions.scripting.core.reloading.GlobalReloadingStrategy;
@@ -37,6 +35,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
@@ -54,9 +53,9 @@
*/
public AtomicBoolean recompileLock = new AtomicBoolean(false);
protected Configuration configuration = new Configuration();
-
+
//ClassDependencies _dependencyMap = new ClassDependencies();
-
+
ImplementationSPI _implementation = null;
GlobalReloadingStrategy _reloadingStrategy = new GlobalReloadingStrategy();
@@ -93,6 +92,41 @@
return ret;
}
+ public Map<String, ClassResource> getAllWatchedResources()
+ {
+ Map<String, ClassResource> ret = new HashMap<String, ClassResource>();
+ for (ScriptingEngine engine : getEngines())
+ {
+ Map<String, ClassResource> watchedResourceMap = engine.getWatchedResources();
+ for (Map.Entry<String, ClassResource> entry : watchedResourceMap.entrySet())
+ {
+ ret.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return ret;
+ }
+
+ public ClassResource getWatchedResource(String key)
+ {
+ for (ScriptingEngine engine : getEngines())
+ {
+ if(!engine.getWatchedResources().containsKey(key)) continue;
+ return engine.getWatchedResources().get(key);
+ }
+ return null;
+ }
+
+ public boolean isTainted(String key) {
+ ClassResource res = getWatchedResource(key);
+ if(res == null) return false;
+ return res.isTainted();
+ }
+
+ public Set<String> loadPossibleDynamicClasses()
+ {
+ return getAllWatchedResources().keySet();
+ }
+
public Configuration getConfiguration()
{
return configuration;
@@ -266,10 +300,11 @@
return o;
}
- public void addDependency(int engineType, String fromClass, String toClass) {
+ public void addDependency(int engineType, String fromClass, String toClass)
+ {
//TODO implement this tomorrow
}
-
+
//----------------------------------------------------------------------
/*public ClassDependencies getDependencyMap()
{
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BaseAnnotationScanListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BaseAnnotationScanListener.java
new file mode 100644
index 0000000..3e6e601
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BaseAnnotationScanListener.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+import org.apache.myfaces.config.RuntimeConfig;
+
+import javax.faces.application.Application;
+import javax.faces.context.FacesContext;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Logger;
+
+/**
+ * Base Class for the JSF2 annotation scanning
+ * (note we do not rely on the impl
+ * for annotation scanning because in the long
+ * run we want to support Mojarra)
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class BaseAnnotationScanListener {
+ Logger _log = Logger.getLogger(this.getClass().getName());
+ static Map<String, Object> _alreadyRegistered = new ConcurrentHashMap<String, Object>(8, 0.75f, 1);
+
+ protected RuntimeConfig getRuntimeConfig() {
+ final FacesContext facesContext = FacesContext.getCurrentInstance();
+ //runtime config not started
+ if (facesContext == null) {
+ return null;
+ }
+ return RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
+ }
+
+ protected Application getApplication() {
+ return FacesContext.getCurrentInstance().getApplication();
+ }
+
+ /**
+ * unregisters this class in the central registry
+ * is triggered if the class itself has been registered previously
+ *
+ * @param className
+ * @return
+ */
+ public void purge(String className) {
+
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BeanImplementationListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BeanImplementationListener.java
new file mode 100644
index 0000000..9c58505
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BeanImplementationListener.java
@@ -0,0 +1,216 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+import org.apache.myfaces.config.RuntimeConfig;
+import org.apache.myfaces.config.element.NavigationRule;
+import org.apache.myfaces.config.impl.digester.elements.ManagedBean;
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.AnnotationScanListener;
+import rewrite.org.apache.myfaces.extensions.scripting.core.common.util.ReflectUtil;
+import rewrite.org.apache.myfaces.extensions.scripting.core.common.util.StringUtils;
+
+import javax.faces.bean.*;
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.logging.Level;
+
+/**
+ * bean implementation listener which registers new java sources
+ * into the runtime config, note this class is not thread safe
+ * it is only allowed to be called from a single thread
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class BeanImplementationListener extends BaseAnnotationScanListener implements AnnotationScanListener
+{
+
+ public boolean supportsAnnotation(String annotation) {
+ return annotation.equals(javax.faces.bean.ManagedBean.class.getName());
+ }
+
+ public boolean supportsAnnotation(Class annotation) {
+ return annotation.equals(javax.faces.bean.ManagedBean.class);
+ }
+
+ public void register(Class clazz, java.lang.annotation.Annotation ann) {
+
+ RuntimeConfig config = getRuntimeConfig();
+
+ javax.faces.bean.ManagedBean annCasted = (javax.faces.bean.ManagedBean) ann;
+
+ String beanName = annCasted.name();
+ if (StringUtils.isBlank(beanName)) {
+ beanName = normalizeName(clazz.getName());
+ }
+
+ beanName = beanName.replaceAll("\"", "");
+ //we need to reregister for every bean due to possible managed prop
+ //and scope changes
+ ManagedBean mbean;
+ if (!hasToReregister(beanName, clazz)) {
+ mbean = (ManagedBean) _alreadyRegistered.get(beanName);
+ //return;
+ } else {
+ mbean = new ManagedBean();
+ }
+
+ mbean.setBeanClass(clazz.getName());
+ mbean.setName(beanName);
+ handleManagedpropertiesCompiled(mbean, fields(clazz));
+ resolveScope(clazz, mbean);
+
+ _alreadyRegistered.put(beanName, mbean);
+ config.addManagedBean(beanName, mbean);
+
+ }
+
+ private void resolveScope(Class clazz, ManagedBean mbean) {
+ //now lets resolve the scope
+ String scope = "none";
+ if (clazz.isAnnotationPresent(RequestScoped.class)) {
+ scope = "request";
+ } else if (clazz.isAnnotationPresent(SessionScoped.class)) {
+ scope = "session";
+ } else if (clazz.isAnnotationPresent(ApplicationScoped.class)) {
+ scope = "application";
+ } else if (clazz.isAnnotationPresent(ViewScoped.class)) {
+ scope = "view";
+ } else if (clazz.isAnnotationPresent(NoneScoped.class)) {
+ scope = "none";
+ } else if (clazz.isAnnotationPresent(CustomScoped.class)) {
+ CustomScoped customScoped = (CustomScoped) clazz.getAnnotation(CustomScoped.class);
+ scope = (customScoped != null) ? customScoped.value() : "custom";
+ }
+ mbean.setScope(scope);
+ }
+
+ private void handleManagedpropertiesCompiled(ManagedBean mbean, Field[] fields) {
+ /*since we reprocess the managed properties we can handle them here by clearing them first*/
+ mbean.getManagedProperties().clear();
+ for (Field field : fields) {
+ if (_log.isLoggable(Level.FINEST)) {
+ _log.log(Level.FINEST, " Scanning field '" + field.getName() + "'");
+ }
+ ManagedProperty property = field
+ .getAnnotation(ManagedProperty.class);
+ if (property != null) {
+ if (_log.isLoggable(Level.FINE)) {
+ _log.log(Level.FINE, " Field '" + field.getName()
+ + "' has a @ManagedProperty annotation");
+ }
+
+ org.apache.myfaces.config.impl.digester.elements.ManagedProperty mpc =
+ new org.apache.myfaces.config.impl.digester.elements.ManagedProperty();
+ String name = property.name();
+ if ((name == null) || "".equals(name)) {
+ name = field.getName();
+ }
+ mpc.setPropertyName(name);
+ mpc.setPropertyClass(field.getType().getName()); // FIXME - primitives, arrays, etc.
+ mpc.setValue(property.value());
+
+ ReflectUtil.executeMethod(mbean, "addProperty", mpc);
+ }
+ }
+ }
+
+ /**
+ * <p>Return an array of all <code>Field</code>s reflecting declared
+ * fields in this class, or in any superclass other than
+ * <code>java.lang.Object</code>.</p>
+ *
+ * @param clazz Class to be analyzed
+ * @return the array of fields
+ */
+ private Field[] fields(Class clazz) {
+
+ Map<String, Field> fields = new HashMap<String, Field>();
+ do {
+ for (Field field : clazz.getDeclaredFields()) {
+ if (!fields.containsKey(field.getName())) {
+ fields.put(field.getName(), field);
+ }
+ }
+ } while ((clazz = clazz.getSuperclass()) != Object.class);
+ return fields.values().toArray(new Field[fields.size()]);
+ }
+
+ protected boolean hasToReregister(String name, Class clazz) {
+ ManagedBean mbean = (ManagedBean) _alreadyRegistered.get(name);
+ return mbean == null || !mbean.getManagedBeanClassName().equals(clazz.getName());
+ }
+
+ /**
+ * name normalizer for automated name mapping
+ * (aka if no name attribute is given in the annotation)
+ *
+ * @param className the classname to be mapped (can be with package=
+ * @return the normalized jsf bean name
+ */
+ private String normalizeName(String className) {
+ String name = className.substring(className.lastIndexOf(".") + 1);
+
+ return name.substring(0, 1).toLowerCase() + name.substring(1);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void purge(String className) {
+ RuntimeConfig config = getRuntimeConfig();
+ //We have to purge and readd our managed beans, unfortunatly the myfaces impl enforces
+ //us to do the same for the nav rules after purge
+ //we cannot purge the managed beans and nav rules separately
+ Collection<NavigationRule> navigationRules = new ArrayList<NavigationRule>();
+ Map managedBeans = new HashMap<String, org.apache.myfaces.config.element.ManagedBean>();
+
+ navigationRules.addAll(config.getNavigationRules());
+ managedBeans.putAll(config.getManagedBeans());
+
+ config.purge();
+
+ for (NavigationRule navRule : navigationRules) {
+ config.addNavigationRule(navRule);
+ }
+
+ //We refresh the managed beans, dead references still can cause
+ //runtime errors but in this case we cannot do anything
+ org.apache.myfaces.config.element.ManagedBean mbeanFound = null;
+ List<String> mbeanKey = new LinkedList<String>();
+
+ for (Object entry : managedBeans.entrySet()) {
+ Map.Entry mbean = (Map.Entry) entry;
+
+ Object bean = mbean.getValue();
+
+
+ if (!((Class)ReflectUtil.executeMethod( bean, "getManagedBeanClass")).getName().equals(className)) {
+ config.addManagedBean((String) mbean.getKey(), (org.apache.myfaces.config.element.ManagedBean) mbean.getValue());
+ } else {
+ Object mbeanf = mbean.getValue();
+ mbeanKey.add((String)ReflectUtil.executeMethod(mbeanf, "getManagedBeanName"));
+ }
+ }
+ if (mbeanFound != null) {
+ for (String toRemove : mbeanKey) {
+ _alreadyRegistered.remove(toRemove);
+ }
+ }
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BehaviorImplementationListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BehaviorImplementationListener.java
new file mode 100644
index 0000000..f7981f9
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BehaviorImplementationListener.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.AnnotationScanListener;
+import rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged.PurgedBehavior;
+
+import javax.faces.component.behavior.FacesBehavior;
+import java.util.logging.Level;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class BehaviorImplementationListener extends SingleEntityAnnotationListener implements AnnotationScanListener
+{
+
+ public BehaviorImplementationListener() {
+ super();
+ _entityParamValue = "value";
+ }
+
+ public boolean supportsAnnotation(String annotation) {
+ return annotation.equals(FacesBehavior.class.getName());
+ }
+
+ public boolean supportsAnnotation(Class annotation) {
+ return annotation.equals(FacesBehavior.class);
+ }
+
+
+ protected void addEntity(Class clazz, String val) {
+ if (_log.isLoggable(Level.FINEST)) {
+ _log.log(Level.FINEST, "addBehavior(" + val + ","
+ + clazz.getName() + ")");
+ }
+ getApplication().addBehavior(val, clazz.getName());
+ }
+
+ @Override
+ public void purge(String className) {
+ super.purge(className);
+ if (!_alreadyRegistered.containsKey(className)) {
+ return;
+ }
+
+ String val = (String) _alreadyRegistered.remove(className);
+ if (val != null) {
+ getApplication().addBehavior(val, PurgedBehavior.class.getName());
+ }
+ }
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BehaviorRendererImplementationListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BehaviorRendererImplementationListener.java
new file mode 100644
index 0000000..9015279
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/BehaviorRendererImplementationListener.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+
+import rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged.PurgedClientBehaviorRenderer;
+
+import javax.faces.FactoryFinder;
+import javax.faces.context.FacesContext;
+import javax.faces.render.FacesBehaviorRenderer;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ * <p/>
+ * Implementation listener for the FacesBehaviorRenderer annotation
+ */
+
+public class BehaviorRendererImplementationListener extends MapEntityAnnotationScanner {
+
+ private static final String PAR_RENDERERTYPE = "rendererType";
+ private static final String PAR_RENDERKITID = "renderKitId";
+
+ Map<AnnotationEntry, String> _inverseIndex = new HashMap<AnnotationEntry, String>();
+
+ class AnnotationEntry {
+ String rendererType;
+ String renderKitId;
+
+ AnnotationEntry(String rendererType, String renderKitId) {
+ this.rendererType = rendererType;
+ this.renderKitId = renderKitId;
+ }
+
+ public boolean equals(Object incoming) {
+ if (!(incoming instanceof AnnotationEntry)) {
+ return false;
+ }
+ AnnotationEntry toCompare = (AnnotationEntry) incoming;
+
+ if (incoming == null) {
+ return false;
+ }
+
+ boolean firstEquals = compareValuePair(rendererType, toCompare.getRendererType());
+ boolean secondEquals = compareValuePair(renderKitId, toCompare.getRenderKitId());
+
+ return firstEquals && secondEquals;
+ }
+
+ @Override
+ public int hashCode() {
+ return (checkForNull(rendererType) + "_" + checkForNull(renderKitId)).hashCode(); //To change body of overridden methods use File | Settings | File Templates.
+ }
+
+ private String checkForNull(String in) {
+ return (in == null) ? "" : in;
+ }
+
+ protected boolean compareValuePair(Object val1, Object val2) {
+ boolean retVal = false;
+ if (val1 == null) {
+ if (val2 != null) retVal = false;
+ if (val2 == null) {
+ retVal = true;
+ }
+ } else {
+ retVal = val1.equals(val2);
+ }
+ return retVal;
+ }
+
+ public String getRendererType() {
+ return rendererType;
+ }
+
+ public String getRenderKitId() {
+ return renderKitId;
+ }
+ }
+
+ public BehaviorRendererImplementationListener() {
+ super();
+ }
+
+ @Override
+ protected void addEntity(Class clazz, Map<String, Object> params) {
+ String value = (String) params.get(PAR_RENDERERTYPE);
+ String renderKitId = (String) params.get(PAR_RENDERKITID);
+
+ AnnotationEntry entry = new AnnotationEntry(value, renderKitId);
+ _alreadyRegistered.put(clazz.getName(), entry);
+ _inverseIndex.put(entry, clazz.getName());
+
+ getApplication().addConverter(entry.getRendererType(), clazz.getName());
+ }
+
+ @Override
+ protected boolean hasToReregister(Map params, Class clazz) {
+ String value = (String) params.get(PAR_RENDERERTYPE);
+ String renderKitId = (String) params.get(PAR_RENDERKITID);
+
+ AnnotationEntry entry = new AnnotationEntry(value, renderKitId);
+
+ AnnotationEntry alreadyRegistered = (AnnotationEntry) _alreadyRegistered.get(clazz.getName());
+ if (alreadyRegistered == null) {
+ return true;
+ }
+
+ return alreadyRegistered.equals(entry);
+ }
+
+ public boolean supportsAnnotation(String annotation) {
+ return annotation.equals(FacesBehaviorRenderer.class.getName());
+ }
+
+ public boolean supportsAnnotation(Class annotation) {
+ return annotation.equals(FacesBehaviorRenderer.class);
+ }
+
+
+ private RenderKitFactory getRenderKitFactory() {
+ return (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+ }
+
+ private RenderKit getRenderkit(String renderKitId) {
+ RenderKitFactory factory = getRenderKitFactory();
+ RenderKit renderKit = factory.getRenderKit(FacesContext.getCurrentInstance(), renderKitId);
+ return renderKit;
+ }
+
+ @Override
+ public void purge(String className) {
+ super.purge(className);
+ AnnotationEntry entry = (AnnotationEntry) _alreadyRegistered.remove(className);
+ if (entry == null) {
+ return;
+ }
+
+ RenderKit renderKit = getRenderkit(entry.getRenderKitId());
+ try {
+ String rendererClass = _inverseIndex.get(entry);
+ if (rendererClass != null && rendererClass.equals(className)) {
+ _inverseIndex.put(entry, PurgedClientBehaviorRenderer.class.getName());
+ renderKit.addClientBehaviorRenderer(entry.getRendererType(), PurgedClientBehaviorRenderer.class.newInstance());
+ }
+ } catch (InstantiationException e) {
+ _log.log(Level.SEVERE, "", e);
+ } catch (IllegalAccessException e) {
+ _log.log(Level.SEVERE, "", e);
+ }
+ }
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ComponentImplementationListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ComponentImplementationListener.java
new file mode 100644
index 0000000..a1d1275
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ComponentImplementationListener.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.AnnotationScanListener;
+import rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged.PurgedComponent;
+
+import javax.faces.component.FacesComponent;
+import java.util.logging.Level;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class ComponentImplementationListener extends SingleEntityAnnotationListener implements AnnotationScanListener
+{
+
+ public ComponentImplementationListener() {
+ super();
+ _entityParamValue = "value";
+ }
+
+ public boolean supportsAnnotation(String annotation) {
+ return annotation.equals(FacesComponent.class.getName());
+ }
+
+ public boolean supportsAnnotation(Class annotation) {
+ return annotation.equals(FacesComponent.class);
+ }
+
+
+ protected void addEntity(Class clazz, String val) {
+ if (_log.isLoggable(Level.FINEST)) {
+ _log.log(Level.FINEST, "addComponent(" + val + "," + clazz.getName() + ")");
+ }
+ getApplication().addComponent(val, clazz.getName());
+ //register the renderer if not registered
+
+ _alreadyRegistered.put(clazz.getName(), val);
+ }
+
+ @Override
+ public void purge(String className) {
+ super.purge(className);
+ //no purge needed we already have a different class
+ //registered
+ if (!_alreadyRegistered.containsKey(className)) {
+ return;
+ }
+ String val = (String) _alreadyRegistered.remove(className);
+ if (val != null) {
+ getApplication().addComponent(val, PurgedComponent.class.getName());
+ }
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ConverterImplementationListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ConverterImplementationListener.java
new file mode 100644
index 0000000..e2e6405
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ConverterImplementationListener.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.AnnotationScanListener;
+import rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged.PurgedConverter;
+
+import javax.faces.application.Application;
+import javax.faces.convert.FacesConverter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class ConverterImplementationListener extends MapEntityAnnotationScanner implements AnnotationScanListener
+{
+
+ private static final String PAR_VALUE = "value";
+ private static final String PAR_DEFAULT = "forClass";
+
+ Map<AnnotationEntry, String> _inverseIndex = new HashMap<AnnotationEntry, String>();
+
+ class AnnotationEntry {
+ String value;
+ Class forClass;
+
+ AnnotationEntry(String value, Class forClass) {
+
+ this.value = value;
+ this.forClass = forClass;
+ }
+
+ public boolean equals(Object incoming) {
+ if (incoming == null) {
+ return false;
+ }
+
+ if (!(incoming instanceof AnnotationEntry)) {
+ return false;
+ }
+ AnnotationEntry toCompare = (AnnotationEntry) incoming;
+
+ boolean firstEquals = compareValuePair(value, toCompare.getValue());
+ boolean secondEquals = compareValuePair(forClass, toCompare.getForClass());
+
+ return firstEquals && secondEquals;
+ }
+
+ @Override
+ public int hashCode() {
+ String retVal = checkForNull(value) + "_";
+ retVal += ((forClass != null) ? forClass.getName() : "");
+ return retVal.hashCode();
+ }
+
+ private String checkForNull(String in) {
+ return (in == null) ? "" : in;
+ }
+
+ protected boolean compareValuePair(Object val1, Object val2) {
+ boolean retVal = false;
+ if (val1 == null) {
+ if (val2 != null) retVal = false;
+ if (val2 == null) {
+ retVal = true;
+ }
+ } else {
+ retVal = val1.equals(val2);
+ }
+ return retVal;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public Class getForClass() {
+ return forClass;
+ }
+ }
+
+ public ConverterImplementationListener() {
+ super(PAR_VALUE, PAR_DEFAULT);
+ }
+
+ @Override
+ protected void addEntity(Class clazz, Map<String, Object> params) {
+ String value = (String) params.get(PAR_VALUE);
+ Class forClass = (Class) params.get(PAR_DEFAULT);
+
+ AnnotationEntry entry = new AnnotationEntry(value, forClass);
+ _alreadyRegistered.put(clazz.getName(), entry);
+ _inverseIndex.put(entry, clazz.getName());
+
+ getApplication().addConverter(entry.getValue(), clazz.getName());
+ }
+
+ @Override
+ protected boolean hasToReregister(Map params, Class clazz) {
+ String value = (String) params.get(PAR_VALUE);
+ Class forClass = (Class) params.get(PAR_DEFAULT);
+
+ AnnotationEntry entry = new AnnotationEntry(value, forClass);
+
+ AnnotationEntry alreadyRegistered = (AnnotationEntry) _alreadyRegistered.get(clazz.getName());
+
+ return (alreadyRegistered == null) || alreadyRegistered.equals(entry);
+ }
+
+ public boolean supportsAnnotation(String annotation) {
+ return annotation.equals(FacesConverter.class.getName());
+ }
+
+ public boolean supportsAnnotation(Class annotation) {
+ return annotation.equals(FacesConverter.class);
+ }
+
+
+ @Override
+ public void purge(String className) {
+ super.purge(className);
+ AnnotationEntry entry = (AnnotationEntry) _alreadyRegistered.remove(className);
+ if (entry == null) {
+ return;
+ }
+ String _oldConverterClass = _inverseIndex.get(entry);
+ if (_oldConverterClass.equals(className)) {
+ Application application = getApplication();
+ application.addConverter(entry.getValue(), PurgedConverter.class.getName());
+ _inverseIndex.put(entry, className);
+ }
+ }
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/GenericAnnotationScanner.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/GenericAnnotationScanner.java
new file mode 100644
index 0000000..20e2523
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/GenericAnnotationScanner.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.AnnotationScanListener;
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.ClassScanListener;
+import rewrite.org.apache.myfaces.extensions.scripting.core.common.ScriptingConst;
+import rewrite.org.apache.myfaces.extensions.scripting.core.context.WeavingContext;
+import rewrite.org.apache.myfaces.extensions.scripting.core.engine.api.ClassScanner;
+import rewrite.org.apache.myfaces.extensions.scripting.core.engine.dependencyScan.loaders.ScannerClassloader;
+
+import javax.faces.context.FacesContext;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ * <p/>
+ * Source path annotation scanner for java it scans all sources in the specified source paths
+ * recursively for additional information
+ * and then adds the id/name -> class binding information to the correct factory locations,
+ * wherever possible
+ */
+@SuppressWarnings("unused")
+public class GenericAnnotationScanner extends BaseAnnotationScanListener implements ClassScanner
+{
+ //eventing system not yet fully implemented
+ List<ClassScanListener> _listeners = new LinkedList<ClassScanListener>();
+
+ //this registry is needed to keep track of added and moved annotations
+ Map<String, String> _registeredAnnotations = new HashMap<String, String>();
+
+ LinkedList<String> _sourcePaths = new LinkedList<String>();
+
+ WeavingContext _weaver = null;
+
+ public GenericAnnotationScanner() {
+ _weaver = WeavingContext.getInstance();
+ initDefaultListeners();
+ }
+
+ public void addScanPath(String sourcePath) {
+ _sourcePaths.addFirst(sourcePath);
+ }
+
+ Collection<java.lang.annotation.Annotation> filterAnnotations(java.lang.annotation.Annotation[] annotations) {
+ List<java.lang.annotation.Annotation> retVal = new ArrayList<java.lang.annotation.Annotation>(annotations.length);
+
+ for (java.lang.annotation.Annotation annotation : annotations) {
+ if (annotation.annotationType().getName().startsWith(ScriptingConst.JAVAX_FACES)) {
+ retVal.add(annotation);
+ }
+
+ }
+ return retVal;
+ }
+
+ public void scanClass(Class clazz) {
+ java.lang.annotation.Annotation[] annotations = clazz.getAnnotations();
+
+ Collection<java.lang.annotation.Annotation> annCol = filterAnnotations(annotations);
+ if (!annCol.isEmpty()) {
+ addOrMoveAnnotations(clazz);
+ } else {
+ removeAnnotations(clazz);
+ }
+ }
+
+ private void initDefaultListeners() {
+ _listeners.add(new BeanImplementationListener());
+ _listeners.add(new BehaviorImplementationListener());
+ _listeners.add(new ComponentImplementationListener());
+ _listeners.add(new ConverterImplementationListener());
+ _listeners.add(new RendererImplementationListener());
+ _listeners.add(new ValidatorImplementationListener());
+ }
+
+ /**
+ * builds up the parsing chain and then notifies its observers
+ * on the found data
+ */
+ public void scanPaths() {
+ //https://issues.apache.org/jira/browse/EXTSCRIPT-33
+
+ //check if the faces config is already available otherwise we cannot scan yet
+ final FacesContext facesContext = FacesContext.getCurrentInstance();
+ //runtime config not started
+ //for now we only can reach the runtime config in the referenced BaseAnnotatonScanListener
+ //if we have a facesContext reachable.
+ if (facesContext == null) {
+ //TODO (1.1) decouple the scan in the BaseAnnotationScanListener from the facesConfig
+ //to get the runtime config
+ return;
+ }
+
+ for (String className : _weaver.loadPossibleDynamicClasses()) {
+ try {
+ if(!_weaver.isTainted(className)) continue;
+
+ ScannerClassloader loader = new ScannerClassloader(Thread.currentThread().getContextClassLoader(),
+ -1, null, _weaver.getConfiguration().getCompileTarget());
+
+ Class clazz;
+ //in case the class does not exist we have to load it from our weavingcontext
+ //otherwise we do just a scan on the class to avoid side behavior
+ //if (WeavingContext.getFileChangedDaemon().getClassMap().get(className) == null) {
+ // clazz = _weaver.loadScriptingClassFromName(className);
+ //} else {
+ clazz = loader.loadClass(className);
+ //}
+
+ if (clazz != null) {
+ java.lang.annotation.Annotation[] anns = clazz.getAnnotations();
+ if (anns != null && anns.length > 0) {
+ addOrMoveAnnotations(clazz);
+ } else {
+ removeAnnotations(clazz);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ Logger _logger = Logger.getLogger(this.getClass().getName());
+ _logger.log(Level.WARNING, "", e);
+ }
+ }
+
+ }
+
+ /**
+ * add or moves a class level annotation
+ * to a new place
+ *
+ * @param clazz the class to have the annotation moved or added
+ */
+ private void addOrMoveAnnotations(Class clazz) {
+ java.lang.annotation.Annotation[] anns = clazz.getAnnotations();
+ for (java.lang.annotation.Annotation ann : anns) {
+ for (ClassScanListener cListener : _listeners) {
+ AnnotationScanListener listener = (AnnotationScanListener) cListener;
+ if (listener.supportsAnnotation(ann.annotationType())) {
+ listener.register(clazz, ann);
+
+ _registeredAnnotations.put(clazz.getName(), ann.annotationType().getName());
+ //TODO check if we still need this
+ //ClassResource metaData = WeavingContext.getInstance().getWatchedResource(clazz.getName());
+
+ }
+ }
+ }
+ }
+
+ /**
+ * use case annotation removed
+ * we have to entirely remove the annotation
+ * from our internal registry and the myfaces registry
+ *
+ * @param clazz the class to have the annotation removed
+ */
+ private void removeAnnotations(Class clazz) {
+ String registeredAnnotation = _registeredAnnotations.get(clazz.getName());
+ if (registeredAnnotation != null) {
+ for (ClassScanListener cListener : _listeners) {
+ AnnotationScanListener listener = (AnnotationScanListener) cListener;
+ if (listener.supportsAnnotation(registeredAnnotation)) {
+ listener.purge(clazz.getName());
+ _registeredAnnotations.remove(clazz.getName());
+ //WeavingContext.getFileChangedDaemon().getClassMap().remove(clazz.getName());
+ }
+ }
+ }
+ }
+
+ public void clearListeners() {
+ _listeners.clear();
+ }
+
+ public void addListener(ClassScanListener listener) {
+ _listeners.add(listener);
+ }
+
+
+ public void scanAndMarkChange() {
+ //do nothing here
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ListenerForAnnotationHandler.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ListenerForAnnotationHandler.java
new file mode 100644
index 0000000..d5c98f0
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ListenerForAnnotationHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+/**
+ * A generic system event listener which makes the system event
+ * annotations dynamic
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class ListenerForAnnotationHandler {
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/MapEntityAnnotationScanner.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/MapEntityAnnotationScanner.java
new file mode 100644
index 0000000..58637e8
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/MapEntityAnnotationScanner.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.AnnotationScanListener;
+import rewrite.org.apache.myfaces.extensions.scripting.core.common.util.ReflectUtil;
+
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Annotation scanner which scans generically
+ * an annotation with more than one entry values.
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public abstract class MapEntityAnnotationScanner extends BaseAnnotationScanListener implements AnnotationScanListener
+{
+
+ String[] _annotationParms = null;
+
+ public MapEntityAnnotationScanner(String... annotationParms) {
+ _annotationParms = annotationParms;
+ }
+
+ public void register(Class clazz, Annotation annotation) {
+
+ Map<String, Object> parms = new HashMap<String, Object>(_annotationParms.length);
+
+ for (String accessor : _annotationParms) {
+ parms.put(accessor, ReflectUtil.fastExecuteMethod(annotation, accessor, new Object[0]));
+ }
+
+ if (hasToReregister(parms, clazz)) {
+ addEntity(clazz, parms);
+ }
+ }
+
+ protected abstract void addEntity(Class clazz, Map<String, Object> params);
+
+ protected abstract boolean hasToReregister(Map params, Class clazz);
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/RendererImplementationListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/RendererImplementationListener.java
new file mode 100644
index 0000000..b708dcd
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/RendererImplementationListener.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.AnnotationScanListener;
+import rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged.PurgedRenderer;
+
+import javax.faces.FactoryFinder;
+import javax.faces.context.FacesContext;
+import javax.faces.render.FacesRenderer;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.Renderer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class RendererImplementationListener extends MapEntityAnnotationScanner implements AnnotationScanListener
+{
+ private static final String PAR_FAMILY = "componentFamily";
+ private static final String PAR_RENDERERTYPE = "rendererType";
+ private static final String PAR_RENDERKITID = "renderKitId";
+
+ Map<AnnotationEntry, String> _inverseIndex = new HashMap<AnnotationEntry, String>();
+
+ public RendererImplementationListener() {
+ super(PAR_FAMILY, PAR_RENDERERTYPE, PAR_RENDERKITID);
+ }
+
+ class AnnotationEntry {
+ String componentFamily;
+ String rendererType;
+ String renderKitId;
+
+ AnnotationEntry(String componentFamily, String rendererType, String renderKitId) {
+ this.componentFamily = componentFamily;
+ this.rendererType = rendererType;
+ this.renderKitId = renderKitId;
+ }
+
+ public boolean equals(Object incoming) {
+ if (!(incoming instanceof AnnotationEntry)) {
+ return false;
+ }
+ AnnotationEntry toCompare = (AnnotationEntry) incoming;
+ //handle null cases
+ if ((componentFamily == null && toCompare.getComponentFamily() != null) ||
+ (componentFamily != null && toCompare.getComponentFamily() == null) ||
+ (rendererType == null && toCompare.getRendererType() != null) ||
+ (rendererType != null && toCompare.getRendererType() == null) ||
+ (renderKitId == null && toCompare.getRenderKitId() != null) ||
+ (renderKitId != null && toCompare.getRenderKitId() == null)) {
+
+ return false;
+ } else if (componentFamily == null && toCompare.getComponentFamily() == null &&
+ rendererType == null && toCompare.getRendererType() == null &&
+ renderKitId == null && toCompare.getRenderKitId() == null) {
+ return true;
+ }
+
+ return componentFamily.equals(toCompare.getComponentFamily()) &&
+ rendererType.equals(toCompare.getRendererType()) &&
+ renderKitId.equals(toCompare.getRenderKitId());
+ }
+
+ @Override
+ public int hashCode() {
+ /*we calculate the hashcoide to avoid double entries*/
+ return (((componentFamily != null) ? componentFamily : "")
+ + "_" +
+ ((rendererType != null) ? rendererType : "")
+ + "_" +
+ ((renderKitId != null) ? renderKitId : "")
+
+ ).hashCode();
+ }
+
+ public String getComponentFamily() {
+ return componentFamily;
+ }
+
+ public String getRendererType() {
+ return rendererType;
+ }
+
+ public String getRenderKitId() {
+ return renderKitId;
+ }
+ }
+
+ public boolean supportsAnnotation(String annotation) {
+ return annotation.equals(FacesRenderer.class.getName());
+ }
+
+ public boolean supportsAnnotation(Class annotation) {
+ return annotation.equals(FacesRenderer.class);
+ }
+
+ @Override
+ protected void addEntity(Class clazz, Map<String, Object> params) {
+ String value = (String) params.get(PAR_FAMILY);
+ String theDefault = (String) params.get(PAR_RENDERERTYPE);
+
+ String renderKitId = getRenderKitId(params);
+ RenderKit renderKit = getRenderkit(renderKitId);
+
+ AnnotationEntry entry = new AnnotationEntry(value, theDefault, renderKitId);
+ _inverseIndex.put(entry, clazz.getName());
+ _alreadyRegistered.put(clazz.getName(), entry);
+
+ if (_log.isLoggable(Level.FINEST)) {
+ _log.log(Level.FINEST, "addRenderer(" + renderKitId + ", "
+ + entry.getComponentFamily() + ", " + entry.getRendererType()
+ + ", " + clazz.getName() + ")");
+ }
+
+ try {
+ renderKit.addRenderer(entry.getComponentFamily(), entry.getRendererType(), (Renderer) clazz.newInstance());
+ } catch (InstantiationException e) {
+ _log.log(Level.SEVERE, "", e);
+ } catch (IllegalAccessException e) {
+ _log.log(Level.SEVERE, "", e);
+ }
+ }
+
+ private RenderKitFactory getRenderKitFactory() {
+ return (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+ }
+
+ @Override
+ protected boolean hasToReregister(Map params, Class clazz) {
+ String value = (String) params.get(PAR_FAMILY);
+ String theDefault = (String) params.get(PAR_RENDERERTYPE);
+ String renderKitId = (String) params.get(PAR_RENDERKITID);
+
+ AnnotationEntry entry = new AnnotationEntry(value, theDefault, renderKitId);
+
+ AnnotationEntry alreadyRegistered = (AnnotationEntry) _alreadyRegistered.get(clazz.getName());
+ if (alreadyRegistered == null) {
+ return true;
+ }
+ //here the check if the new class is the same as the old one
+ return alreadyRegistered.equals(entry);
+ }
+
+ private String getRenderKitId(Map<String, Object> params) {
+ String renderKitId = (String) params.get(PAR_RENDERKITID);
+ renderKitId = (renderKitId == null) ? getApplication().getDefaultRenderKitId() : renderKitId;
+ return renderKitId;
+ }
+
+ private RenderKit getRenderkit(String renderKitId) {
+ RenderKitFactory factory = getRenderKitFactory();
+ RenderKit renderKit = factory.getRenderKit(FacesContext.getCurrentInstance(), renderKitId);
+ return renderKit;
+ }
+
+ @Override
+ public void purge(String className) {
+ super.purge(className);
+ AnnotationEntry entry = (AnnotationEntry) _alreadyRegistered.remove(className);
+ if (entry == null) {
+ return;
+ }
+
+ RenderKit renderKit = getRenderkit(entry.getRenderKitId());
+ try {
+ //by fetching the changed renderer we save a full rescan
+ String rendererClass = _inverseIndex.get(entry);
+ if (rendererClass != null && rendererClass.equals(className)) {
+ _inverseIndex.put(entry, PurgedRenderer.class.getName());
+ renderKit.addRenderer(entry.getComponentFamily(), entry.getRendererType(), PurgedRenderer.class.newInstance());
+ }
+ } catch (InstantiationException e) {
+ _log.log(Level.SEVERE, "", e);
+ } catch (IllegalAccessException e) {
+ _log.log(Level.SEVERE, "", e);
+ }
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/SingleEntityAnnotationListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/SingleEntityAnnotationListener.java
new file mode 100644
index 0000000..a6bd1fb
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/SingleEntityAnnotationListener.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+import org.apache.myfaces.extensions.scripting.core.util.ReflectUtil;
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.AnnotationScanListener;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * annotation scanner which generalized
+ * scans annotations with one value entry
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public abstract class SingleEntityAnnotationListener extends BaseAnnotationScanListener implements AnnotationScanListener
+{
+ String _entityParamValue = null;
+
+ public void register(Class clazz, Annotation annotation) {
+
+ String val = (String) ReflectUtil.executeMethod(annotation, _entityParamValue);
+ if (hasToReregister(val, clazz)) {
+ addEntity(clazz, val);
+ }
+ }
+
+ protected abstract void addEntity(Class clazz, String val);
+
+ protected boolean hasToReregister(String name, Class clazz) {
+ String componentClass = (String) _alreadyRegistered.get(name);
+ return componentClass == null || !componentClass.equals(clazz.getName());
+ }
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ValidatorImplementationListener.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ValidatorImplementationListener.java
new file mode 100644
index 0000000..9848378
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/ValidatorImplementationListener.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation;
+
+import rewrite.org.apache.myfaces.extensions.scripting.core.api.AnnotationScanListener;
+import rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged.PurgedValidator;
+
+import javax.faces.validator.FacesValidator;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class ValidatorImplementationListener extends MapEntityAnnotationScanner implements AnnotationScanListener
+{
+
+ private static final String PAR_VALUE = "value";
+ private static final String PAR_DEFAULT = "isDefault";
+
+ Map<AnnotationEntry, String> _inverseIndex = new HashMap<AnnotationEntry, String>();
+
+ public ValidatorImplementationListener() {
+ /*supported annotation parameters rendererType and default*/
+ super(PAR_VALUE, PAR_DEFAULT);
+ }
+
+ class AnnotationEntry {
+ String value;
+ Boolean theDefault;
+
+ AnnotationEntry(String value, Boolean theDefault) {
+ this.value = value;
+ this.theDefault = theDefault;
+ }
+
+ public boolean equals(Object incoming) {
+ if (!(incoming instanceof AnnotationEntry)) {
+ return false;
+ }
+ AnnotationEntry toCompare = (AnnotationEntry) incoming;
+
+ if (incoming == null) {
+ return false;
+ }
+
+ boolean firstEquals = compareValuePair(value, toCompare.getValue());
+ boolean secondEquals = compareValuePair(theDefault, toCompare.getTheDefault());
+
+ return firstEquals && secondEquals;
+ }
+
+ @Override
+ public int hashCode() {
+ String retVal = checkForNull(value) + "_" + checkForNull(theDefault);
+ return retVal.hashCode();
+ }
+
+ private String checkForNull(String in) {
+ return (in == null) ? "" : in;
+ }
+
+ private String checkForNull(Boolean in) {
+ return (in == null) ? "" : String.valueOf(in.booleanValue());
+ }
+
+ protected boolean compareValuePair(Object val1, Object val2) {
+ boolean retVal = false;
+ if (val1 == null) {
+ if (val2 != null) retVal = false;
+ if (val2 == null) {
+ retVal = true;
+ }
+ } else {
+ retVal = val1.equals(val2);
+ }
+ return retVal;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public Boolean getTheDefault() {
+ return theDefault;
+ }
+ }
+
+ public boolean supportsAnnotation(String annotation) {
+ return annotation.equals(FacesValidator.class.getName());
+ }
+
+ public boolean supportsAnnotation(Class annotation) {
+ return annotation.equals(FacesValidator.class);
+ }
+
+
+ @Override
+ protected void addEntity(Class clazz, Map<String, Object> params) {
+ String value = (String) params.get(PAR_VALUE);
+ Boolean theDefault = (Boolean) params.get(PAR_DEFAULT);
+
+ AnnotationEntry entry = new AnnotationEntry(value, theDefault);
+ _alreadyRegistered.put(clazz.getName(), entry);
+ _inverseIndex.put(entry, clazz.getName());
+
+ getApplication().addValidator(entry.getValue(), clazz.getName());
+ }
+
+ @Override
+ protected boolean hasToReregister(Map params, Class clazz) {
+ String value = (String) params.get(PAR_VALUE);
+ Boolean theDefault = (Boolean) params.get(PAR_DEFAULT);
+
+ AnnotationEntry entry = new AnnotationEntry(value, theDefault);
+
+ AnnotationEntry alreadyRegistered = (AnnotationEntry) _alreadyRegistered.get(clazz.getName());
+ if (alreadyRegistered == null) {
+ return true;
+ }
+
+ return alreadyRegistered.equals(entry);
+ }
+
+ @Override
+ public void purge(String className) {
+ super.purge(className);
+ AnnotationEntry entry = (AnnotationEntry) _alreadyRegistered.get(className);
+ if (entry == null) {
+ return;
+ }
+
+ String oldValidator = _inverseIndex.get(entry);
+ if (oldValidator.equals(className)) {
+ _alreadyRegistered.remove(className);
+ getApplication().addValidator(entry.getValue(), PurgedValidator.class.getName());
+ _inverseIndex.put(entry, PurgedValidator.class.getName());
+ }
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedBehavior.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedBehavior.java
new file mode 100644
index 0000000..0a19f31
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedBehavior.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import javax.faces.component.behavior.Behavior;
+import javax.faces.event.BehaviorEvent;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedBehavior implements Behavior {
+ public void broadcast(BehaviorEvent event) {
+ throw new RuntimeException("Behavior does not exist");
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedClientBehaviorRenderer.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedClientBehaviorRenderer.java
new file mode 100644
index 0000000..86623b3
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedClientBehaviorRenderer.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import javax.faces.render.ClientBehaviorRenderer;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedClientBehaviorRenderer extends ClientBehaviorRenderer {
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedComponent.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedComponent.java
new file mode 100644
index 0000000..29bbd0d
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedComponent.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import javax.faces.component.UIOutput;
+
+/**
+ * We override the component from a real family so that
+ * so that myfaces can handle it in a decent way
+ * directly from UIComponent it would fail
+ * unless we implement everything family etc... all by our own
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedComponent extends UIOutput {
+ public PurgedComponent() {
+ super();
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedConverter.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedConverter.java
new file mode 100644
index 0000000..432762b
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedConverter.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedConverter implements Converter {
+ private static final String DOES_NOT_EXIST = "Converter does not exist";
+
+ public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedELResolver.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedELResolver.java
new file mode 100644
index 0000000..ba55f26
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedELResolver.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import org.apache.myfaces.extensions.scripting.api.Decorated;
+
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import java.util.Iterator;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedELResolver extends ELResolver implements Decorated {
+
+ private final String DOES_NOT_EXIST = "EL Resolver does not exist";
+
+ ELResolver _delegate;
+
+ public PurgedELResolver(ELResolver delegate) {
+ _delegate = delegate;
+ }
+
+ @Override
+ public Object getValue(ELContext elContext, Object o, Object o1) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public Class getType(ELContext elContext, Object o, Object o1) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public void setValue(ELContext elContext, Object o, Object o1, Object o2) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public boolean isReadOnly(ELContext elContext, Object o, Object o1) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public Iterator getFeatureDescriptors(ELContext elContext, Object o) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public Class getCommonPropertyType(ELContext elContext, Object o) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ public ELResolver getDelegate() {
+ return _delegate;
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedLifecycle.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedLifecycle.java
new file mode 100644
index 0000000..c559028
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedLifecycle.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import org.apache.myfaces.extensions.scripting.api.Decorated;
+
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseListener;
+import javax.faces.lifecycle.Lifecycle;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedLifecycle extends Lifecycle implements Decorated {
+
+ private static final String DOES_NOT_EXIST = "Lifecycle does not exist";
+
+ Lifecycle _delegate;
+
+ public PurgedLifecycle(Lifecycle delegate) {
+ _delegate = delegate;
+ }
+
+ @Override
+ public void addPhaseListener(PhaseListener listener) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public void execute(FacesContext context) throws FacesException {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public PhaseListener[] getPhaseListeners() {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public void removePhaseListener(PhaseListener listener) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public void render(FacesContext context) throws FacesException {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ public Object getDelegate() {
+ return _delegate;
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedNavigationHandler.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedNavigationHandler.java
new file mode 100644
index 0000000..d7e2b87
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedNavigationHandler.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import org.apache.myfaces.extensions.scripting.api.Decorated;
+
+import javax.faces.application.NavigationHandler;
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedNavigationHandler extends NavigationHandler implements Decorated {
+
+ NavigationHandler _delegate;
+
+ public PurgedNavigationHandler(NavigationHandler delegate) {
+ _delegate = delegate;
+ }
+
+ @Override
+ public void handleNavigation(FacesContext context, String fromAction, String outcome) {
+ throw new RuntimeException("Navigation handler does not exist");
+ }
+
+ public NavigationHandler getDelegate() {
+ return _delegate;
+ }
+
+ public void setDelegate(NavigationHandler delegate) {
+ _delegate = delegate;
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedRenderer.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedRenderer.java
new file mode 100644
index 0000000..d626127
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedRenderer.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.ConverterException;
+import javax.faces.render.Renderer;
+import java.io.IOException;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedRenderer extends Renderer {
+ private static final String DOES_NOT_EXIST = "Renderer does not exist";
+
+ public PurgedRenderer() {
+ super();
+ }
+
+ @Override
+ public void decode(FacesContext context, UIComponent component) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public String convertClientId(FacesContext context, String clientId) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public boolean getRendersChildren() {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedRenderkit.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedRenderkit.java
new file mode 100644
index 0000000..6e18a76
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedRenderkit.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import org.apache.myfaces.extensions.scripting.api.Decorated;
+
+import javax.faces.context.ResponseStream;
+import javax.faces.context.ResponseWriter;
+import javax.faces.render.RenderKit;
+import javax.faces.render.Renderer;
+import javax.faces.render.ResponseStateManager;
+import java.io.OutputStream;
+import java.io.Writer;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedRenderkit extends RenderKit implements Decorated {
+
+ private static final String DOES_NOT_EXIST = "Renderkit does not exist";
+
+ RenderKit _delegate;
+
+ public PurgedRenderkit(RenderKit delegate) {
+ _delegate = delegate;
+ }
+
+ @Override
+ public void addRenderer(String family, String rendererType, Renderer renderer) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public ResponseStream createResponseStream(OutputStream out) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public ResponseWriter createResponseWriter(Writer writer, String contentTypeList, String characterEncoding) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public Renderer getRenderer(String family, String rendererType) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public ResponseStateManager getResponseStateManager() {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ public RenderKit getDelegate() {
+ return _delegate;
+ }
+
+ public void setDelegate(RenderKit delegate) {
+ _delegate = delegate;
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedResourceHandler.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedResourceHandler.java
new file mode 100644
index 0000000..9dfdcc1
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedResourceHandler.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import org.apache.myfaces.extensions.scripting.api.Decorated;
+
+import javax.faces.application.Resource;
+import javax.faces.application.ResourceHandler;
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class PurgedResourceHandler extends ResourceHandler implements Decorated {
+
+ private static final String DOES_NOT_EXIST = "Resource Handler does not exist";
+
+ ResourceHandler _delegate;
+
+ public PurgedResourceHandler(ResourceHandler delegate) {
+ _delegate = delegate;
+ }
+
+ @Override
+ public Resource createResource(String resourceName) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public Resource createResource(String resourceName, String libraryName) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public Resource createResource(String resourceName, String libraryName, String contentType) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public String getRendererTypeForResourceName(String resourceName) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public void handleResourceRequest(FacesContext context) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public boolean isResourceRequest(FacesContext context) {
+ throw new RuntimeException(DOES_NOT_EXIST);
+ }
+
+ @Override
+ public boolean libraryExists(String libraryName) {
+ return false;
+ }
+
+ public ResourceHandler getDelegate() {
+ return _delegate;
+ }
+
+ public void setDelegate(ResourceHandler delegate) {
+ _delegate = delegate;
+ }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedValidator.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedValidator.java
new file mode 100644
index 0000000..4574a4c
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/annotation/purged/PurgedValidator.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package rewrite.org.apache.myfaces.extensions.scripting.jsf.annotation.purged;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ * <p/>
+ * Purged validator class to enable validator
+ * purging despite the fact
+ * that the original code does not allow it
+ */
+
+public class PurgedValidator implements Validator {
+
+ public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
+ throw new RuntimeException("Validator does not exist");
+ }
+
+}