Repository: empire-db Updated Branches: refs/heads/master bcff43b89 -> 1f1259b61
EMPIREDB-235 Project: http://git-wip-us.apache.org/repos/asf/empire-db/repo Commit: http://git-wip-us.apache.org/repos/asf/empire-db/commit/1f1259b6 Tree: http://git-wip-us.apache.org/repos/asf/empire-db/tree/1f1259b6 Diff: http://git-wip-us.apache.org/repos/asf/empire-db/diff/1f1259b6 Branch: refs/heads/master Commit: 1f1259b6165a519a0bedd1c1f81361f66966eac0 Parents: bcff43b Author: Rainer Döbele <[email protected]> Authored: Thu Jan 28 17:57:16 2016 +0100 Committer: Rainer Döbele <[email protected]> Committed: Thu Jan 28 17:57:16 2016 +0100 ---------------------------------------------------------------------- .../empire/jsf2/app/WebAppStartupListener.java | 103 ++++ .../apache/empire/jsf2/app/WebApplication.java | 509 +++++++++++++++++++ .../empire/jsf2/impl/FacesImplementation.java | 88 ++++ .../empire/jsf2/impl/MojarraImplementation.java | 98 ++++ .../empire/jsf2/impl/MyFacesImplementation.java | 80 +++ .../empire/jsf2/impl/ResourceTextResolver.java | 120 +++++ 6 files changed, 998 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/empire-db/blob/1f1259b6/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebAppStartupListener.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebAppStartupListener.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebAppStartupListener.java new file mode 100644 index 0000000..a8531d6 --- /dev/null +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebAppStartupListener.java @@ -0,0 +1,103 @@ +/* + * 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 org.apache.empire.jsf2.app; + +import javax.faces.application.Application; +import javax.faces.context.FacesContext; +import javax.faces.event.AbortProcessingException; +import javax.faces.event.PostConstructApplicationEvent; +import javax.faces.event.PreDestroyApplicationEvent; +import javax.faces.event.SystemEvent; +import javax.faces.event.SystemEventListener; +import javax.servlet.ServletContext; + +import org.apache.empire.jsf2.impl.FacesImplementation; +import org.apache.empire.jsf2.impl.MojarraImplementation; +import org.apache.empire.jsf2.impl.MyFacesImplementation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WebAppStartupListener implements SystemEventListener +{ + private static final Logger log = LoggerFactory.getLogger(WebAppStartupListener.class); + + @Override + public boolean isListenerForSource(Object source) + { + return (source instanceof Application); + } + + @Override + public void processEvent(SystemEvent event) + throws AbortProcessingException + { + log.info("ApplicationStartupListener:processEvent"); + if (event instanceof PostConstructApplicationEvent) + { + FacesContext startupContext = FacesContext.getCurrentInstance(); + // detect implementation + FacesImplementation facesImplementation = detectFacesImplementation(); + Object app = facesImplementation.getManagedBean(WebApplication.APPLICATION_BEAN_NAME, startupContext); + if (!(app instanceof WebApplication)) + throw new AbortProcessingException("Error: Application is not a "+WebApplication.class.getName()+" instance. Please create a ApplicationFactory!"); + // Create and Init application + WebApplication facesApp = (WebApplication)app; + facesApp.init(facesImplementation, startupContext); + // Set Servlet Attribute + ServletContext servletContext = (ServletContext) startupContext.getExternalContext().getContext(); + if (servletContext.getAttribute(WebApplication.APPLICATION_BEAN_NAME)!=facesApp) + { + log.warn("WARNING: Ambiguous application definition. An object of name '{}' already exists on application scope!", WebApplication.APPLICATION_BEAN_NAME); + } + } + else if (event instanceof PreDestroyApplicationEvent) + { + log.info("Processing PreDestroyApplicationEvent"); + } + + } + + /** + * Detects the JSF Implementation and returns an implmentation handler class. + * Supported Implementations are Sun Mojarra (2.2.x) and Apache MyFaces (2.2.x) + * @return + */ + protected FacesImplementation detectFacesImplementation() + { + log.debug("Detecting JSF-Implementation..."); + // Test for Apache MyFaces + try { + Class.forName("org.apache.myfaces.application.ApplicationFactoryImpl"); + return new MyFacesImplementation(); + } catch (ClassNotFoundException e) { + // It's not MyFaces + } + // Test for Sun Mojarra + try { + Class.forName("com.sun.faces.application.ApplicationFactoryImpl"); + return new MojarraImplementation(); + } catch (ClassNotFoundException e) { + // It's not Mojarra + } + // Not found + log.error("JSF-Implementation missing or unknown. Please make sure either Apache MyFaces or Sun Mojarra implementation is provided"); + throw new UnsupportedOperationException(); + } + +} http://git-wip-us.apache.org/repos/asf/empire-db/blob/1f1259b6/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java new file mode 100644 index 0000000..0afee55 --- /dev/null +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java @@ -0,0 +1,509 @@ +/* + * 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 org.apache.empire.jsf2.app; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +import javax.faces.FactoryFinder; +import javax.faces.application.Application; +import javax.faces.application.ApplicationFactory; +import javax.faces.application.FacesMessage; +import javax.faces.application.FacesMessage.Severity; +import javax.faces.component.NamingContainer; +import javax.faces.component.UIComponent; +import javax.faces.component.UIViewRoot; +import javax.faces.context.FacesContext; +import javax.servlet.ServletContext; +import javax.sql.DataSource; + +import org.apache.empire.commons.StringUtils; +import org.apache.empire.data.DataType; +import org.apache.empire.db.DBDatabase; +import org.apache.empire.exceptions.InternalException; +import org.apache.empire.exceptions.InvalidArgumentException; +import org.apache.empire.exceptions.NotSupportedException; +import org.apache.empire.jsf2.controls.TextAreaInputControl; +import org.apache.empire.jsf2.controls.TextInputControl; +import org.apache.empire.jsf2.impl.FacesImplementation; +import org.apache.empire.jsf2.impl.ResourceTextResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// import com.sun.faces.application.ApplicationImpl; + +public abstract class WebApplication +{ + private static final Logger log = LoggerFactory.getLogger(WebApplication.class); + + private static final String CONNECTION_ATTRIBUTE = "dbConnections"; + + public static String APPLICATION_BEAN_NAME = "webApplication"; + + protected TextResolver[] textResolvers = null; + + private String webRoot = null; + + private FacesImplementation facesImpl = null; + + private static WebApplication appInstance = null; + + public static WebApplication getInstance() + { + if (appInstance==null) + log.warn("No WebApplication instance available. Please add a PostConstructApplicationEvent using WebAppStartupListener in your faces-config.xml to create the WebApplication object."); + // return instance + return appInstance; + } + + protected abstract void init(ServletContext servletContext); + + protected abstract DataSource getAppDataSource(DBDatabase db); + + protected WebApplication() + { // subscribe + log.info("WebApplication {0} created", getClass().getName()); + // Must be a singleton + if (appInstance!=null) { + throw new RuntimeException("An attempt was made to create second instance of WebApplication. WebApplication must be a singleton!"); + } + // set Instance + appInstance = this; + } + + /** + * Init the Application + * @param servletContext + */ + public final void init(FacesImplementation facesImpl, FacesContext startupContext) + { + // Only call once! + if (this.facesImpl!=null || this.webRoot!=null) + throw new NotSupportedException(this, "init"); + // set imppl + this.facesImpl = facesImpl; + // webRoot + ServletContext servletContext = (ServletContext) startupContext.getExternalContext().getContext(); + webRoot = servletContext.getContextPath(); + servletContext.setAttribute("webRoot", webRoot); + servletContext.setAttribute("app", this); + // Init + init(servletContext); + // text resolvers + log.info("*** initTextResolvers() ***"); + ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY); + Application app = appFactory.getApplication(); + initTextResolvers(app); + // Log info + log.info("*** WebApplication initialization complete ***"); + log.info("JSF-Implementation is '{}'", facesImpl.getClass().getName()); + log.info("WebRoot is '{}'", webRoot); + } + + /* Context handling */ + + /** + * handle request cleanup + * @param ctx + */ + public void onRequestComplete(final FacesContext ctx) + { + releaseAllConnections(ctx); + } + + /** + * handle view change + * @param fc + * @param viewId + */ + public void onChangeView(final FacesContext fc, String viewId) + { + // allow custom view change logic + + // clear page resources + Map<String, Object> sm = FacesUtils.getSessionMap(fc); + if (sm!=null) + sm.remove(FacesUtils.PAGE_RESOURCE_MAP_ATTRIBUTE); + } + + public void addJavascriptCall(final FacesContext fc, String function) + { + throw new NotSupportedException(this, "addJavascriptCall"); + } + + /** + * return the interface for Implementation specific features + * that are specific for Mojarra or MyFaces + */ + public FacesImplementation getFacesImplementation() + { + return facesImpl; + } + + /** + * returns the web context path as returned from ServletContext.getContextPath() + */ + public String getWebRoot() + { + return webRoot; + } + + /** + * returns the active locale for a given FacesContext + */ + public Locale getContextLocale(final FacesContext ctx) + { + UIViewRoot root; + // Start out with the default locale + Locale locale; + Locale defaultLocale = Locale.getDefault(); + locale = defaultLocale; + // See if this FacesContext has a ViewRoot + if (null != (root = ctx.getViewRoot())) + { + // If so, ask it for its Locale + if (null == (locale = root.getLocale())) + { + // If the ViewRoot has no Locale, fall back to the default. + locale = defaultLocale; + } + } + return locale; + } + + public TextResolver getTextResolver(Locale locale) + { + // No text Resolvers provided + if (textResolvers == null || textResolvers.length == 0) + { + throw new NotSupportedException(this, "getTextResolver"); + } + // Lookup resolver for locale + for (int i = 0; i < textResolvers.length; i++) + if (locale.equals(textResolvers[i].getLocale())) + return textResolvers[i]; + // locale not found: return default + return textResolvers[0]; + } + + public TextResolver getTextResolver(FacesContext ctx) + { + return getTextResolver(getContextLocale(ctx)); + } + + /** + * checks if the current context contains an error + * @param fc the FacesContext + * @return true if the context has an error set or false otherwise + */ + public boolean hasError(final FacesContext fc) + { + Iterator<FacesMessage> msgIterator = fc.getMessages(); + if (msgIterator != null) + { // Check Messages + while (msgIterator.hasNext()) + { // Check Severity + Severity fms = msgIterator.next().getSeverity(); + if (fms == FacesMessage.SEVERITY_ERROR || fms == FacesMessage.SEVERITY_FATAL) + return true; + } + } + return false; + } + + /** + * returns true if a form input element has been partially submitted + * @param fc the Faces Context + * @return the componentId or null if no partial submit was been performed + */ + public boolean isPartialSubmit(final FacesContext fc) + { + // Override for your JSF component Framework. e.g. for IceFaces + // Map<String,String> parameterMap = fc.getExternalContext().getRequestParameterMap(); + // return ObjectUtils.getBoolean(parameterMap.get("ice.submit.partial")); + return false; + } + + /** + * returns the componentId for which a partial submit has been performed. + * @param fc the Faces Context + * @return the componentId or null if no partial submit was been performed + */ + public String getPartialSubmitComponentId(final FacesContext fc) + { + // Override for your JSF component Framework. e.g. for IceFaces + // Map<String,String> parameterMap = fc.getExternalContext().getRequestParameterMap(); + // return parameterMap.get("ice.event.captured"); + return null; + } + + /** + * finds the component with the given id that is located in the same NamingContainer as a given component + * @param fc the FacesContext + * @param componentId the component id + * @param nearComponent a component within the same naming container from which to start the search (optional) + * @return the component or null if no component was found + */ + public UIComponent findComponent(FacesContext fc, String componentId, UIComponent nearComponent) + { + if (StringUtils.isEmpty(componentId)) + throw new InvalidArgumentException("componentId", componentId); + // Begin search near given component (if any) + UIComponent component = null; + if (nearComponent != null) + { // Search below the nearest naming container + component = nearComponent.findComponent(componentId); + if (component == null) + { // Recurse upwards + UIComponent nextParent = nearComponent; + while (true) + { + nextParent = nextParent.getParent(); + // search NamingContainers only + while (nextParent != null && !(nextParent instanceof NamingContainer)) + { + nextParent = nextParent.getParent(); + } + if (nextParent == null) + { + break; + } + else + { + component = nextParent.findComponent(componentId); + } + if (component != null) + { + break; + } + } + } + } + // Not found. Search the entire tree + if (component == null) + component = findChildComponent(fc.getViewRoot(), componentId); + // done + return component; + } + + /** + * finds a child component with the given id that is located below the given parent component + * @param parent the parent + * @param componentId the component id + * @return the component or null if no component was found + */ + public static UIComponent findChildComponent(UIComponent parent, String componentId) + { + UIComponent component = null; + if (parent.getChildCount() == 0) + return null; + Iterator<UIComponent> children = parent.getChildren().iterator(); + while (children.hasNext()) + { + UIComponent nextChild = children.next(); + if (nextChild instanceof NamingContainer) + { + component = nextChild.findComponent(componentId); + } + if (component == null) + { + component = findChildComponent(nextChild, componentId); + } + if (component != null) + { + break; + } + } + return component; + } + + /** + * returns the default input control type for a given data Type + * @see org.apache.empire.jsf2.controls.InputControlManager + * @param dataType + * @return an Input Cnotrol type + */ + public String getDefaultControlType(DataType dataType) + { + switch (dataType) + { + case CLOB: + return TextAreaInputControl.NAME; + default: + return TextInputControl.NAME; + } + } + + /* Message handling */ + + protected void initTextResolvers(Application app) + { + int count = 0; + Iterator<Locale> locales = app.getSupportedLocales(); + for (count = 0; locales.hasNext(); count++) + { + locales.next(); + } + + // get message bundles + String messageBundle = app.getMessageBundle(); + textResolvers = new TextResolver[count]; + locales = app.getSupportedLocales(); + for (int i = 0; locales.hasNext(); i++) + { + Locale locale = locales.next(); + textResolvers[i] = new ResourceTextResolver(ResourceBundle.getBundle(messageBundle, locale)); + log.info("added TextResolver for {} bundle='{}'", locale.getLanguage(), messageBundle); + } + } + + /** + * returns a connection from the connection pool + * + * @return + */ + protected Connection getConnection(DBDatabase db) + { + // Get From Pool + try + { // Obtain a connection + Connection conn = getAppDataSource(db).getConnection(); + conn.setAutoCommit(false); + return conn; + } + catch (SQLException e) + { + log.error("Failed to get connection from pool.", e); + throw new InternalException(e); + } + } + + /** + * releases a connection from the connection pool + */ + protected void releaseConnection(DBDatabase db, Connection conn, boolean commit) + { + try + { // release connection + if (conn == null) + { + return; + } + // Commit or rollback connection depending on the exit code + if (commit) + { // success: commit all changes + db.commit(conn); + log.debug("REQUEST {}: commited."); + } + else + { // failure: rollback all changes + db.rollback(conn); + log.debug("REQUEST {}: rolled back."); + } + // Release Connection + conn.close(); + // done + if (log.isDebugEnabled()) + log.debug("REQUEST {}: returned connection to pool."); + } + catch (SQLException e) + { + log.error("Error releasing connection", e); + e.printStackTrace(); + } + } + + /** + * returns a connection for the current Request + */ + public Connection getConnectionForRequest(FacesContext fc, DBDatabase db) + { + if (fc == null) + throw new InvalidArgumentException("FacesContext", fc); + if (db == null) + throw new InvalidArgumentException("DBDatabase", db); + // Get Conneciton map + @SuppressWarnings("unchecked") + Map<DBDatabase, Connection> connMap = (Map<DBDatabase, Connection>) FacesUtils.getRequestAttribute(fc, CONNECTION_ATTRIBUTE); + if (connMap != null && connMap.containsKey(db)) + return connMap.get(db); + // Pooled Connection + Connection conn = getConnection(db); + if (conn == null) + return null; + // Add to map + if (connMap == null) + { + connMap = new HashMap<DBDatabase, Connection>(); + FacesUtils.setRequestAttribute(fc, CONNECTION_ATTRIBUTE, connMap); + } + connMap.put(db, conn); + return conn; + } + + /** + * releases the current request connection + * @param fc the FacesContext + * @param commit when true changes are committed otherwise they are rolled back + */ + public void releaseAllConnections(final FacesContext fc, boolean commit) + { + @SuppressWarnings("unchecked") + Map<DBDatabase, Connection> connMap = (Map<DBDatabase, Connection>) FacesUtils.getRequestAttribute(fc, CONNECTION_ATTRIBUTE); + if (connMap != null) + { // Walk the connection map + for (Map.Entry<DBDatabase, Connection> e : connMap.entrySet()) + { + releaseConnection(e.getKey(), e.getValue(), commit); + } + // remove from request map + FacesUtils.setRequestAttribute(fc, CONNECTION_ATTRIBUTE, null); + } + } + + public void releaseAllConnections(final FacesContext fc) + { + releaseAllConnections(fc, !hasError(fc)); + } + + public void releaseConnection(final FacesContext fc, DBDatabase db, boolean commit) + { + @SuppressWarnings("unchecked") + Map<DBDatabase, Connection> connMap = (Map<DBDatabase, Connection>) FacesUtils.getRequestAttribute(fc, CONNECTION_ATTRIBUTE); + if (connMap != null && connMap.containsKey(db)) + { // Walk the connection map + releaseConnection(db, connMap.get(db), commit); + connMap.remove(db); + if (connMap.size() == 0) + FacesUtils.setRequestAttribute(fc, CONNECTION_ATTRIBUTE, null); + } + } + + public void releaseConnection(final FacesContext fc, DBDatabase db) + { + releaseConnection(fc, db, !hasError(fc)); + } + + +} http://git-wip-us.apache.org/repos/asf/empire-db/blob/1f1259b6/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/FacesImplementation.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/FacesImplementation.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/FacesImplementation.java new file mode 100644 index 0000000..630cb6c --- /dev/null +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/FacesImplementation.java @@ -0,0 +1,88 @@ +/* + * 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 org.apache.empire.jsf2.impl; + +import javax.el.ValueExpression; +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; + +public interface FacesImplementation +{ + /** + * Registers a managed bean + * + * Implementation for Mojarra: + * --------------------------- + * FacesContext fc = FacesContext.getCurrentInstance(); + * BeanManager bm = ApplicationAssociate.getInstance(fc.getExternalContext()).getBeanManager(); + * // check + * if (bm.getRegisteredBeans().containsKey(beanName)) + * throw new ItemExistsException(beanName); + * // register now + * ManagedBeanInfo mbi = new ManagedBeanInfo(beanName, beanClass, "view", null, null, null, null); + * bm.register(mbi); + * + * + * Implementation for MyFaces: + * --------------------------- + * FacesContext fc = FacesContext.getCurrentInstance(); + * RuntimeConfig rc = RuntimeConfig.getCurrentInstance(fc.getExternalContext()); + * // check + * if (rc.getManagedBeans().containsKey(beanName)) + * throw new ItemExistsException(beanName); + * // register now + * ManagedBean mbi = new ManagedBean(); + * mbi.setName(beanName); + * mbi.setBeanClass(beanClass); + * mbi.setScope(scope); + * rc.addManagedBean(beanName, mbi); + * + */ + void registerManagedBean(final String beanName, final String beanClass, final String scope); + + /** + * Returns the parentComponent for a given ValueExpression. + * + * Implementation example: + * ----------------------- + * final ELContext elcontext = fc.getELContext(); + * final Application application = fc.getApplication(); + * return application.getELResolver().getValue(elcontext, null, beanName); + * + */ + public Object getManagedBean(final String beanName, final FacesContext fc); + + /** + * Return the parentComponent for a given ValueExpression. + * + * Implementation for Mojarra: + * --------------------------- + * if (ve instanceof ContextualCompositeValueExpression) + * { + * FacesContext ctx = FacesContext.getCurrentInstance(); + * ContextualCompositeValueExpression ccve = (ContextualCompositeValueExpression)ve; + * CompositeComponentStackManager manager = CompositeComponentStackManager.getManager(ctx); + * UIComponent cc = manager.findCompositeComponentUsingLocation(ctx, ccve.getLocation()); + * // set Parent + * return cc; + * } + */ + UIComponent getValueParentComponent(final ValueExpression ve); + +} http://git-wip-us.apache.org/repos/asf/empire-db/blob/1f1259b6/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MojarraImplementation.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MojarraImplementation.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MojarraImplementation.java new file mode 100644 index 0000000..e0a5562 --- /dev/null +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MojarraImplementation.java @@ -0,0 +1,98 @@ +/* + * 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 org.apache.empire.jsf2.impl; + +import java.util.Map; + +import javax.el.ValueExpression; +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; + +import org.apache.empire.exceptions.ItemExistsException; +import org.apache.empire.jsf2.app.WebApplication; + +import com.sun.faces.application.ApplicationAssociate; +import com.sun.faces.application.ApplicationFactoryImpl; +import com.sun.faces.application.InjectionApplicationFactory; +import com.sun.faces.component.CompositeComponentStackManager; +import com.sun.faces.facelets.el.ContextualCompositeValueExpression; +import com.sun.faces.mgbean.BeanManager; +import com.sun.faces.mgbean.ManagedBeanInfo; + +public class MojarraImplementation implements FacesImplementation +{ + private BeanManager bm; + + /* + @Override + public void initApplication(final FacesApplication application) + { + ApplicationFactoryImpl applFactoryImpl = new ApplicationFactoryImpl(); + // set impl + application.setImplementation(this, applFactoryImpl.getApplication()); + // Application Map + Map<String, Object> appMap = FacesContext.getCurrentInstance().getExternalContext().getApplicationMap(); + appMap.put(InjectionApplicationFactory.class.getName(), application); + // init Bean Manager + FacesContext fc = FacesContext.getCurrentInstance(); + bm = ApplicationAssociate.getInstance(fc.getExternalContext()).getBeanManager(); + } + */ + + @Override + public void registerManagedBean(final String beanName,final String beanClass,final String scope) + { + // check + if (bm.getRegisteredBeans().containsKey(beanName)) + { + throw new ItemExistsException(beanName); + } + // register now + ManagedBeanInfo mbi = new ManagedBeanInfo(beanName, beanClass, "view", null, null, null, null); + bm.register(mbi); + } + + @Override + public Object getManagedBean(final String beanName, final FacesContext fc) + { + // Find Bean + if (bm==null) + bm = ApplicationAssociate.getInstance(fc.getExternalContext()).getBeanManager(); + Object mbean = bm.getBeanFromScope(beanName, fc); + if (mbean==null) + mbean= bm.create(beanName, fc); + return mbean; + } + + @Override + public UIComponent getValueParentComponent(final ValueExpression ve) + { + if (ve instanceof ContextualCompositeValueExpression) + { + FacesContext ctx = FacesContext.getCurrentInstance(); + ContextualCompositeValueExpression ccve = (ContextualCompositeValueExpression)ve; + CompositeComponentStackManager manager = CompositeComponentStackManager.getManager(ctx); + UIComponent cc = manager.findCompositeComponentUsingLocation(ctx, ccve.getLocation()); + // set Parent + return cc; + } + return null; + } + +} http://git-wip-us.apache.org/repos/asf/empire-db/blob/1f1259b6/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MyFacesImplementation.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MyFacesImplementation.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MyFacesImplementation.java new file mode 100644 index 0000000..2b60a52 --- /dev/null +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/MyFacesImplementation.java @@ -0,0 +1,80 @@ +/* + * 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 org.apache.empire.jsf2.impl; + +import javax.el.ELContext; +import javax.el.ValueExpression; +import javax.faces.application.Application; +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; + +import org.apache.empire.exceptions.ItemExistsException; +import org.apache.myfaces.config.RuntimeConfig; +import org.apache.myfaces.config.impl.digester.elements.ManagedBeanImpl; + +public class MyFacesImplementation implements FacesImplementation +{ + /* + @Override + public void initApplication(FacesApplication application) + { + ApplicationFactoryImpl applFactoryImpl = new ApplicationFactoryImpl(); + // set impl + application.setImplementation(this, applFactoryImpl.getApplication()); + applFactoryImpl.setApplication(application); + } + */ + + @Override + public void registerManagedBean(final String beanName, final String beanClass, final String scope) { + + // get Runtime Config + FacesContext fc = FacesContext.getCurrentInstance(); + RuntimeConfig rc = RuntimeConfig.getCurrentInstance(fc.getExternalContext()); + // check + if (rc.getManagedBeans().containsKey(beanName)) + { + throw new ItemExistsException(beanName); + } + // register now + // ManagedBean mbi = new ManagedBean(); --> Use this for Myfaces 2.1.x + ManagedBeanImpl mbi = new ManagedBeanImpl(); // new since Myfaces 2.2.x + mbi.setName(beanName); + mbi.setBeanClass(beanClass); + mbi.setScope(scope); + rc.addManagedBean(beanName, mbi); + } + + @Override + public Object getManagedBean(final String beanName, final FacesContext fc) + { + // Find Bean + final ELContext elcontext = fc.getELContext(); + final Application application = fc.getApplication(); + return application.getELResolver().getValue(elcontext, null, beanName); + } + + @Override + public UIComponent getValueParentComponent(final ValueExpression ve) + { + /* No implmentation for MyFaces currently available */ + return null; + } + +} http://git-wip-us.apache.org/repos/asf/empire-db/blob/1f1259b6/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/ResourceTextResolver.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/ResourceTextResolver.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/ResourceTextResolver.java new file mode 100644 index 0000000..e01eae9 --- /dev/null +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/ResourceTextResolver.java @@ -0,0 +1,120 @@ +/* + * 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 org.apache.empire.jsf2.impl; + +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.apache.empire.exceptions.EmpireException; +import org.apache.empire.jsf2.app.TextResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ResourceTextResolver implements TextResolver +{ + private static final Logger log = LoggerFactory.getLogger(ResourceTextResolver.class); + + public static String MSG_KEY_INDICATOR = "!"; + + private final ResourceBundle resBundle; + + public ResourceTextResolver(ResourceBundle resBundle) + { + this.resBundle = resBundle; + } + + public final ResourceBundle getResourceBundle() + { + return resBundle; + } + + public final Locale getLocale() + { + return resBundle.getLocale(); + } + + public String resolveKey(String key) + { + try + { + String res = resBundle.getString(key); + if (res==null) + throw new MissingResourceException("Message Key not found.", String.class.getSimpleName(), key); + return res; + } + catch (MissingResourceException e) + { + log.error("Message key missing '{}'.", key); + return "["+key+"]"; + } + catch (Exception e) + { + log.error("Error resolving text: {}", e); + return "["+key+"]"; + } + } + + public String resolveText(String text) + { + // Translate + if (text != null && text.startsWith(MSG_KEY_INDICATOR)) + { + String key = text.substring(1); + return resolveKey(key); + } + return text; + } + + public String getExceptionMessage(Exception e) + { + if (e instanceof EmpireException) + { + EmpireException ee = (EmpireException)e; + String key = ee.getErrorType().getKey(); + // get Pattern + String pattern; + if (resBundle.containsKey(key)) + { // Get Pattern + pattern = resBundle.getString(key); + } + else + { // No error message pattern provided. Using default + pattern = ee.getErrorType().getMessagePattern(); + log.error("Error resolving error messsage pattern: {}", key); + } + // get Params and translate + String[] params = ee.getErrorParams(); + if (params!=null) + { for (int i=0; i<params.length; i++) + params[i] = resolveText(params[i]); + } + // Format message + return EmpireException.formatErrorMessage(ee.getErrorType(), pattern, params); + } + else + { // Other exception try to resolve by class name + String key = "exception."+e.getClass().getName(); + if (resBundle.containsKey(key)) + return resBundle.getString(key); + // not provided + return e.getLocalizedMessage(); + } + } +}
