I don't think that anyone will port your complete code and give you a complete solution ;)
The biggest problem is AFAIR that the renderer implementations are not in the API packages. So you have to rebuild all this functionality without dependencies to the Impl. e.g. Attribute,AttributeManager -> String[] with attribute namens Move all the utils functions to your own code (Util.componentIsDisabled, RenderKitUtils.getSelectItems. etc.) The most code doesn't really depent on the IMPL code. 2014-02-13 12:44 GMT+01:00 Rene Perschon <chummer_r...@gmx.net>: > Hi everyone! > > I'm currently migrating an application from Glassfish 3.1.1 to TomEE. Now > the problem is that this application contains a custom component which was > unfortunately coded with hard dependencies on com.sun.faces classes (maven > dependency jsf-impl). > > Now my question is how can i port this component in such a way that it is > independent from any concrete JSF implementation (or at least in such a way > that it works with MyFaces). > > Here's the component: > > import java.io.IOException; > import java.util.Iterator; > import java.util.Map; > > import javax.faces.component.UIComponent; > import javax.faces.component.UINamingContainer; > import javax.faces.component.ValueHolder; > import javax.faces.context.FacesContext; > import javax.faces.context.ResponseWriter; > import javax.faces.convert.Converter; > import javax.faces.model.SelectItem; > import javax.faces.model.SelectItemGroup; > > import com.sun.faces.renderkit.Attribute; > import com.sun.faces.renderkit.AttributeManager; > import com.sun.faces.renderkit.RenderKitUtils; > import com.sun.faces.renderkit.html_basic.MenuRenderer; > import com.sun.faces.util.RequestStateManager; > import com.sun.faces.util.Util; > > /** > * {@inheritDoc}. > */ > public class CustomSelectManyCheckboxListRenderer extends MenuRenderer > { > /** {@inheritDoc}. */ > private static final Attribute[] ATTRIBUTES = > AttributeManager.getAttributes(AttributeManager.Key.SELECTMANYCHECKBOX); > /** Representing the border string. */ > private static final String BORDER = "border"; > /** Representing the tr string. */ > private static final String TR = "tr"; > /** Representing the td string. */ > private static final String TD = "td"; > /** Representing the label string. */ > private static final String LABEL = "label"; > /** Representing the newline string. */ > private static final String NEWLINE = "\n"; > /** Representing the tab string. */ > private static final String TAB = "\t"; > /** Representing the class string. */ > private static final String CLASS = "class"; > /** Representing the style string. */ > private static final String STYLE = "style"; > /** Representing the valign string. */ > private static final String VALIGN = "valign"; > > > // ---------------------------------------------------------- Public > Methods > > > @Override > public void encodeEnd(FacesContext context, UIComponent component) > throws IOException > { > > rendererParamsNotNull(context, component); > > if (!shouldEncode(component)) > { > return; > } > > ResponseWriter writer = context.getResponseWriter(); > assert (writer != null); > > String alignStr; > Object borderObj; > boolean alignVertical = false; > int border = 0; > > > > if (null != component.getAttributes().get("layout")) > { > alignStr = (String) component.getAttributes().get("layout"); > alignVertical = alignStr.equalsIgnoreCase("pageDirection"); > } > > if (null != component.getAttributes().get(BORDER)) > { > borderObj = component.getAttributes().get(BORDER); > border = (Integer) borderObj; > } > > Converter converter = null; > if (component instanceof ValueHolder) > { > converter = ((ValueHolder)component).getConverter(); > } > > renderBeginText(component, border, alignVertical, context, true); > > Iterator<SelectItem> items = > RenderKitUtils.getSelectItems(context, component); > > Object currentSelections = getCurrentSelectedValues(component); > Object[] submittedValues = getSubmittedSelectedValues(component); > Map<String, Object> attributes = component.getAttributes(); > OptionComponentInfo optionInfo = > new OptionComponentInfo((String) > attributes.get("disabledClass"), > (String) > attributes.get("enabledClass"), > (String) > attributes.get("unselectedClass"), > (String) > attributes.get("selectedClass"), > Util.componentIsDisabled(component), > isHideNoSelection(component)); > int idx = -1; > while (items.hasNext()) > { > SelectItem curItem = items.next(); > idx++; > // If we come across a group of options, render them as a > nested > // table. > if (curItem instanceof SelectItemGroup) > { > // write out the label for the group. > if (curItem.getLabel() != null) > { > if (alignVertical) > { > writer.startElement(TR, component); > } > writer.startElement(TD, component); > writer.writeText(curItem.getLabel(), component, LABEL); > writer.endElement(TD); > if (alignVertical) > { > writer.endElement(TR); > } > > } > if (alignVertical) > { > writer.startElement(TR, component); > } > writer.startElement(TD, component); > writer.writeText(NEWLINE, component, null); > renderBeginText(component, 0, alignVertical, > context, false); > // render options of this group. > SelectItem[] itemsArray = > ((SelectItemGroup) curItem).getSelectItems(); > for (int i = 0; i < itemsArray.length; ++i) > { > renderOption(context, > component, > converter, > itemsArray[i], > currentSelections, > submittedValues, > alignVertical, > i, > optionInfo); > } > renderEndText(component, alignVertical, context); > writer.endElement(TD); > if (alignVertical) > { > writer.endElement(TR); > writer.writeText(NEWLINE, component, null); > } > } > else > { > renderOption(context, > component, > converter, > curItem, > currentSelections, > submittedValues, > alignVertical, > idx, > optionInfo); > } > } > > renderEndText(component, alignVertical, context); > > } > > // ------------------------------------------------------- Protected > Methods > > > /** > * {@inheritDoc} > */ > @Override > protected boolean isBehaviorSource(FacesContext ctx, > String behaviorSourceId, > String componentClientId) > { > > if (behaviorSourceId == null) > { > return false; > } > char sepChar = UINamingContainer.getSeparatorChar(ctx); > String actualBehaviorId = > behaviorSourceId.substring(0, > behaviorSourceId.lastIndexOf(sepChar)); > return (actualBehaviorId.equals(componentClientId)); > > } > > /** > * {@inheritDoc} > */ > protected void renderBeginText(UIComponent component, int border, > boolean alignVertical, FacesContext > context, > boolean outerTable) throws IOException > { > ResponseWriter writer = context.getResponseWriter(); > assert (writer != null); > > writer.startElement("table", component); > if (border != Integer.MIN_VALUE) > { > writer.writeAttribute(BORDER, border, BORDER); > } > > // render style and styleclass attribute on the outer table > instead of > // rendering it as pass through attribute on every option in the > list. > if (outerTable) > { > // render "id" only for outerTable. > if (shouldWriteIdAttribute(component)) > { > writeIdAttributeIfNecessary(context, writer, component); > } > String styleClass = (String) component.getAttributes().get( > "styleClass"); > String style = (String) component.getAttributes().get(STYLE); > if (styleClass != null) > { > writer.writeAttribute(CLASS, styleClass, CLASS); > } > if (style != null) > { > writer.writeAttribute(STYLE, style, STYLE); > } > } > writer.writeText(NEWLINE, component, null); > > if (!alignVertical) > { > writer.writeText(TAB, component, null); > writer.startElement(TR, component); > writer.writeText(NEWLINE, component, null); > } > > } > > /** > * {@inheritDoc} > */ > protected void renderEndText(UIComponent component, > boolean alignVertical, > FacesContext context) throws IOException > { > > ResponseWriter writer = context.getResponseWriter(); > assert (writer != null); > > if (!alignVertical) > { > writer.writeText(TAB, component, null); > writer.endElement(TR); > writer.writeText(NEWLINE, component, null); > } > writer.endElement("table"); > > } > > /** > * {@inheritDoc} > */ > protected void renderOption(FacesContext context, > UIComponent component, > Converter converter, > SelectItem curItem, > Object currentSelections, > Object[] submittedValues, > boolean alignVertical, > int itemNumber, > OptionComponentInfo optionInfo) throws > IOException > { > > String valueString = getFormattedValue(context, component, > curItem.getValue(), > converter); > > Object valuesArray; > Object itemValue; > if (submittedValues != null) > { > valuesArray = submittedValues; > itemValue = valueString; > } > else > { > valuesArray = currentSelections; > itemValue = curItem.getValue(); > } > > RequestStateManager.set(context, > > RequestStateManager.TARGET_COMPONENT_ATTRIBUTE_NAME, > component); > > boolean isSelected = isSelected(context, component, itemValue, > valuesArray, converter); > if (optionInfo.isHideNoSelection() && > curItem.isNoSelectionOption() && > currentSelections != null && > !isSelected) > { > return; > } > > ResponseWriter writer = context.getResponseWriter(); > assert (writer != null); > > if (alignVertical) > { > writer.writeText(TAB, component, null); > writer.startElement(TR, component); > writer.writeText(NEWLINE, component, null); > } > writer.startElement(TD, component); > writer.writeAttribute(VALIGN, "top", VALIGN); > writer.writeText(NEWLINE, component, null); > > writer.startElement("input", component); > writer.writeAttribute("name", component.getClientId(context), > "clientId"); > String idString = component.getClientId(context) + > UINamingContainer.getSeparatorChar(context) + > Integer.toString(itemNumber); > writer.writeAttribute("id", idString, "id"); > > writer.writeAttribute("value", valueString, "value"); > writer.writeAttribute("type", "checkbox", null); > > if (isSelected) > { > writer.writeAttribute(getSelectedTextString(), Boolean.TRUE, > null); > } > > // Don't render the disabled attribute twice if the 'parent' > // component is already marked disabled. > if (!optionInfo.isDisabled()) > { > if (curItem.isDisabled()) > { > writer.writeAttribute("disabled", true, "disabled"); > } > } > > // Apply HTML 4.x attributes specified on UISelectMany component > to all > // items in the list except styleClass and style which are > rendered as > // attributes of outer most table. > RenderKitUtils.renderPassThruAttributes(context, > writer, > component, > ATTRIBUTES, > > getNonOnClickSelectBehaviors(component)); > > RenderKitUtils.renderXHTMLStyleBooleanAttributes(writer, > component); > > RenderKitUtils.renderSelectOnclick(context, component, true); > > writer.endElement("input"); > > //-------------------------------------------------------- > // New stuff for event selecting > //-------------------------------------------------------- > > writer.endElement(TD); > > // starting the label td > writer.startElement(TD, component); > writer.writeAttribute(VALIGN, "top", VALIGN); > writer.writeAttribute("width", "80px", "width"); > writer.writeAttribute(STYLE, "padding-top:4px", STYLE); > > String itemLabel = curItem.getLabel(); > if (itemLabel == null) > { > itemLabel = valueString; > } > > writer.writeText(" ", component, null); > writer.startElement(LABEL, component); > writer.writeAttribute("for", component.getClientId() + ":" + > itemNumber, "for"); > if (!curItem.isEscape()) > { > // It seems the ResponseWriter API should > // have a writeText() with a boolean property > // to determine if it content written should > // be escaped or not. > writer.write(itemLabel); > } > else > { > writer.writeText(itemLabel, component, null); > } > writer.endElement(LABEL); > > isSelected(context, component, itemValue, valuesArray, converter); > // if (isSelected(context, component, itemValue, valuesArray, > converter)) > // { > // // selected > // } > // else > // { > // // not selected > // } > writer.endElement(TD); > > // starting the description td > writer.startElement(TD, component); > writer.writeAttribute(VALIGN, "top", VALIGN); > writer.writeAttribute(STYLE, "padding-top:4px", STYLE); > > String itemLabelDesc = curItem.getDescription(); > if (itemLabelDesc == null) > { > itemLabelDesc = ""; > } > writer.writeText(" ", component, null); > if (!curItem.isEscape()) > { > // It seems the ResponseWriter API should > // have a writeText() with a boolean property > // to determine if it content written should > // be escaped or not. > writer.write(itemLabelDesc); > } > else > { > writer.writeText(itemLabelDesc, component, null); > } > > writer.endElement(TD); > > //-------------------------------------------------------- > // New stuff for event selecting end > //-------------------------------------------------------- > > writer.writeText(NEWLINE, component, null); > if (alignVertical) > { > writer.writeText(TAB, component, null); > writer.endElement(TR); > writer.writeText(NEWLINE, component, null); > } > } > > > // ------------------------------------------------- Package Private > Methods > > /** > * {@inheritDoc} > */ > String getSelectedTextString() > { > return "checked"; > } > } > > > Any help is appreciated! > Thanks! > > René >