Permalink
Browse files

View handler that checks if there are any auto-generated IDs rendered.

  • Loading branch information...
arjantijms committed Jun 26, 2014
1 parent 4ea6584 commit c83e4ab509fb5a2fbbe4f26ea43300f7199478a3
Showing with 125 additions and 0 deletions.
  1. +125 −0 src/main/java/org/omnifaces/viewhandler/NoAutoGeneratedIdViewHandler.java
@@ -0,0 +1,125 @@
/*
* Copyright 2014 OmniFaces.
*
* Licensed 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.omnifaces.viewhandler;
import static javax.faces.component.UINamingContainer.getSeparatorChar;
import static javax.faces.component.UIViewRoot.UNIQUE_ID_PREFIX;
import static org.omnifaces.util.Components.getCurrentComponent;
import java.io.IOException;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.application.ViewHandlerWrapper;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextWrapper;
import javax.faces.context.ResponseWriter;
import javax.faces.context.ResponseWriterWrapper;
/**
* This view handler once installed will throw an exception whenever an automatically generated id (<code>j_idt...</code>)
* is encountered in the rendered output.
* <p>
* Note that this does not check every component for its ID directly, but instead checks the {@link ResponseWriter} for
* writes to the "id" attribute. Components that write their markup in any other way won't be checked and will thus
* slip through.
*
* @since 2.0
* @author Arjan Tijms
*/
public class NoAutoGeneratedIdViewHandler extends ViewHandlerWrapper {
// Private constants ----------------------------------------------------------------------------------------------
private static final String ERROR_AUTO_GENERATED_ID_ENCOUNTERED =
"Auto generated ID '%s' encountered. Current component type: '%s'. Parent component type: '%s' with ID '%s'.";
// Properties -----------------------------------------------------------------------------------------------------
private ViewHandler wrapped;
// Constructors ---------------------------------------------------------------------------------------------------
/**
* Construct a new No Auto Generated Id view handler around the given wrapped view handler.
*
* @param wrapped
* The wrapped view handler.
*/
public NoAutoGeneratedIdViewHandler(ViewHandler wrapped) {
this.wrapped = wrapped;
}
// Actions --------------------------------------------------------------------------------------------------------
@Override
public void renderView(final FacesContext context, final UIViewRoot viewToRender) throws IOException, FacesException {
final String INTERMEDIATE_ID_PREFIX = getSeparatorChar(context) + UNIQUE_ID_PREFIX;
super.renderView(new FacesContextWrapper() {
@Override
public void setResponseWriter(final javax.faces.context.ResponseWriter responseWriter) {
super.setResponseWriter(new ResponseWriterWrapper() {
@Override
public void writeAttribute(String name, Object value, String property) throws IOException {
if ("id".equals(name) && isGeneratedID(value)) {
UIComponent currentComponent = getCurrentComponent();
UIComponent parentComponent = currentComponent == null ? null : currentComponent.getParent();
throw new IllegalStateException(String.format(ERROR_AUTO_GENERATED_ID_ENCOUNTERED,
value,
currentComponent == null ? "<current component null>" : currentComponent.getClass().getName(),
parentComponent == null ? "<parent component null>" : parentComponent.getClass().getName(),
parentComponent == null ? "<no parent ID>" : parentComponent.getId()
));
}
super.writeAttribute(name, value, property);
};
private boolean isGeneratedID(Object value) {
return value != null && (value.toString().startsWith(UNIQUE_ID_PREFIX) || value.toString().contains(INTERMEDIATE_ID_PREFIX));
}
@Override
public ResponseWriter getWrapped() {
return responseWriter;
}
});
};
@Override
public FacesContext getWrapped() {
return context;
}
} , viewToRender);
}
@Override
public ViewHandler getWrapped() {
return wrapped;
}
}

0 comments on commit c83e4ab

Please sign in to comment.