/** @since 3.9.0 */ public class MenuModificationExtension extends AbstractMenuExtension { private static final IScoutLogger LOG = ScoutLogManager.getLogger(MenuModificationExtension.class); private final Class<? extends IMenuModifier<? extends IMenu>> m_menuModifier; public MenuModificationExtension( Class<? extends IMenu> menuClass, IMenuExtensionFilter filter, Class<? extends IMenuModifier<? extends IMenu>> menuModifier) { super(menuClass, filter); if (menuModifier == null) { throw new IllegalArgumentException("menuModifier must not be null"); } // check assignability of given menu class along with the type parameter defined on the menu // modifier Class<?> menuModifierMenuType = TypeCastUtility.getGenericsParameterClass(menuModifier, IMenuModifier.class); if (menuModifierMenuType == null) { LOG.warn( "could not determine generic type parameter of menu modifier '" + menuModifier.getName() + ";"); } else if (!menuModifierMenuType.isAssignableFrom(menuClass)) { throw new IllegalArgumentException( "menuClass must be assignalbe to the generic type of given menuModifier. [menuClass: '" + menuClass.getName() + "', generic type on menuModifier: '" + menuModifierMenuType.getName() + "'"); } m_menuModifier = menuModifier; } public Class<? extends IMenuModifier<? extends IMenu>> getMenuModifier() { return m_menuModifier; } @Override public boolean accept(Object anchor, Object container, IMenu menu) { if (!getMenuClass().isInstance(menu)) { return false; } return super.accept(anchor, container, menu); } @SuppressWarnings("unchecked") public <T extends IMenu> IMenuModifier<T> createMenuModifier() throws ProcessingException { try { return (IMenuModifier<T>) m_menuModifier.newInstance(); } catch (Exception e) { throw new ProcessingException( "Error while instantiating menu modifier '" + m_menuModifier.getName() + "'.", e); } } }
/** Grid (model) layout of split box only visible parts are used */ public class SplitBoxGrid { private static final IScoutLogger LOG = ScoutLogManager.getLogger(SplitBoxGrid.class); private ISplitBox m_splitBox = null; private IFormField[] m_fields; private int m_gridColumns; private int m_gridRows; public SplitBoxGrid(ISplitBox splitBox) { m_splitBox = splitBox; } public void validate() { // reset m_gridColumns = 2; m_gridRows = 1; ArrayList<IFormField> list = new ArrayList<IFormField>(); // filter for (IFormField f : m_splitBox.getFields()) { if (f.isVisible()) { list.add(f); } else { GridData data = GridDataBuilder.createFromHints(f, 1); f.setGridDataInternal(data); } } m_fields = list.toArray(new IFormField[list.size()]); layoutStatic(); } private void layoutStatic() { int x = 0; for (int i = 0; i < m_fields.length; i++) { GridData data = GridDataBuilder.createFromHints(m_fields[i], 1); data.x = x; data.y = 0; if (data.weightX < 0) { data.weightX = data.w; } m_fields[i].setGridDataInternal(data); x = x + data.w; m_gridRows = Math.max(m_gridRows, data.h); } m_gridColumns = x; } public int getGridColumnCount() { return m_gridColumns; } public int getGridRowCount() { return m_gridRows; } }
public final class FormFieldsExtensionPoint { private static IScoutLogger LOG = ScoutLogManager.getLogger(FormFieldsExtensionPoint.class); private FormFieldsExtensionPoint() {} public static IFormFieldExtension[] getFormFieldExtensions() { ArrayList<IFormFieldExtension> formFieldExtensionList = new ArrayList<IFormFieldExtension>(); IExtensionRegistry reg = Platform.getExtensionRegistry(); IExtensionPoint xp = reg.getExtensionPoint(Activator.PLUGIN_ID, "formfields"); IExtension[] extensions = xp.getExtensions(); for (IExtension extension : extensions) { IConfigurationElement[] elements = extension.getConfigurationElements(); for (IConfigurationElement element : elements) { String name = element.getAttribute("name"); boolean active = "true".equalsIgnoreCase(element.getAttribute("active")); FormFieldExtension formFieldExt = new FormFieldExtension(name); formFieldExt.setContibuterBundleId(extension.getContributor().getName()); formFieldExt.setActive(active); formFieldExt.setScope(getScopePriority(element.getAttribute("scope"))); formFieldExt.setModelClassName(element.getAttribute("modelClass")); formFieldExt.setFactoryClassName(getClassName(element.getChildren("factory"), "class")); formFieldExt.setUiClassName(getClassName(element.getChildren("uiClass"), "class")); formFieldExtensionList.add(formFieldExt); } } return formFieldExtensionList.toArray(new IFormFieldExtension[formFieldExtensionList.size()]); } private static String getClassName(IConfigurationElement[] elements, String attribute) { String clazzName = null; if (elements != null && elements.length == 1) { clazzName = elements[0].getAttribute(attribute); } return clazzName; } private static int getScopePriority(String scope) { int prio = IFormFieldExtension.SCOPE_DEFAULT; if (StringUtility.isNullOrEmpty(scope) || scope.equalsIgnoreCase("default")) { prio = IFormFieldExtension.SCOPE_DEFAULT; } else if (scope.equalsIgnoreCase("global")) { prio = IFormFieldExtension.SCOPE_GLOBAL; } return prio; } }
public class ClientNotificationPollingJob extends ClientAsyncJob { private static final IScoutLogger LOG = ScoutLogManager.getLogger(ClientNotificationPollingJob.class); private long m_pollInterval; private boolean m_analyzeNetworkLatency; public ClientNotificationPollingJob( IClientSession session, long pollInterval, boolean analyzeNetworkLatency) { super("Client notification fetcher", session, true); updatePollingValues(pollInterval, analyzeNetworkLatency); } public void updatePollingValues(long pollInterval, boolean analyzeNetworkLatency) { m_pollInterval = Math.max(1000L, pollInterval); m_analyzeNetworkLatency = analyzeNetworkLatency; } @Override protected IStatus runStatus(IProgressMonitor monitor) { IPingService pingService = SERVICES.getService(IPingService.class); try { // side-effect of every service call (whether ping or any other) is to get // client notifications pingService.ping("GetClientNotifications"); } catch (Throwable t) { if (LOG.isInfoEnabled()) { LOG.info("polling", t); } } if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } else { // re-schedule long netLatency = 0L; IPerformanceAnalyzerService perf = SERVICES.getService(IPerformanceAnalyzerService.class); if (perf != null) { netLatency = perf.getNetworkLatency(); } long sleepInterval = m_analyzeNetworkLatency ? Math.max(m_pollInterval, 10 * netLatency) : m_pollInterval; schedule(sleepInterval); return Status.OK_STATUS; } } }
/** * Adapter to convert a <code>xsd:dateTime</code> to a {@link Date} and vice versa. For both * directions, the transformation is in respect to the default timezone accessible by {@link * TimeZone#getDefault()}. If no timezone is provided at all, the date is interpreted to be local to * the default timezone. * * <p>The {@link String} provided must correspond to the <code>xsd:dateTime</code> format defined on * <a * href="http://www.w3.org/TR/xmlschema-2/#dateTime">http://www.w3.org/TR/xmlschema-2/#dateTime</a>. * The format was inspired by [ISO 8601] but with timezone information included, because in [ISO * 8601], a time is only represented as local time or in relation to UTC (Zulu time). * * <p> * * <h2>Definition of xsd:dateTime format</h2> * * <b> Format: <code>'-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?</code></b> * * <ul> * <li>'-'? <em>yyyy</em> is a four-or-more digit optionally negative-signed numeral that * represents the year; if more than four digits, leading zeros are prohibited, and '0000' is * prohibited; also note that a plus sign is <b>not</b> permitted); * <li>the remaining '-'s are separators between parts of the date portion; * <li>the first <em>mm</em> is a two-digit numeral that represents the month; * <li><em>dd</em> is a two-digit numeral that represents the day; * <li>'T' is a separator indicating that time-of-day follows; * <li><em>hh</em> is a two-digit numeral that represents the hour; '24' is permitted if the * minutes and seconds represented are zero, and the <code>dateTime</code> value so * represented is the first instant of the following day (the hour property of a <code> * dateTime</code> object cannot have a value greater than 23); * <li>':' is a separator between parts of the time-of-day portion; * <li>the second <em>mm</em> is a two-digit numeral that represents the minute; * <li><em>ss</em> is a two-integer-digit numeral that represents the whole seconds; * <li>'.' <em>s+</em> (if present) represents the fractional seconds; * <li><em>zzzzzz</em> (if present) represents the timezone. * </ul> */ public class DefaultTimezoneDateAdapter extends XmlAdapter<String, Date> { private static final IScoutLogger LOG = ScoutLogManager.getLogger(DefaultTimezoneDateAdapter.class); public DefaultTimezoneDateAdapter() {} @Override public String marshal(Date date) throws Exception { if (date == null) { return null; } long utcMillis = date.getTime(); GregorianCalendar calendar = new GregorianCalendar(TimeZone.getDefault()); calendar.setTimeInMillis(utcMillis); DatatypeFactory factory = DatatypeFactory.newInstance(); XMLGregorianCalendar xmlCalendar = factory.newXMLGregorianCalendar(calendar); return xmlCalendar.toXMLFormat(); } @Override public Date unmarshal(String rawValue) throws Exception { if (!StringUtility.hasText(rawValue)) { return null; } // local time of given timezone (or default timezone if not applicable) DatatypeFactory factory = DatatypeFactory.newInstance(); XMLGregorianCalendar xmlCalendar = factory.newXMLGregorianCalendar(rawValue); GregorianCalendar calendar = xmlCalendar.toGregorianCalendar(); long utcMillis = calendar.getTimeInMillis(); // default time Calendar defaultTimezoneCalendar = Calendar.getInstance(); defaultTimezoneCalendar.setTimeInMillis(utcMillis); return defaultTimezoneCalendar.getTime(); } }
/** convenience subclass of {@link AbstractDateField} with hasDate=true and hasTime=true */ @ClassId("7475d45c-396f-44c5-bb72-4610d980d3ac") public abstract class AbstractDateTimeField extends AbstractDateField { private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractDateTimeField.class); public AbstractDateTimeField() { this(true); } public AbstractDateTimeField(boolean callInitializer) { super(callInitializer); } @Override protected boolean getConfiguredHasTime() { return true; } /** UpdateDisplayTextOnModify is not supported for DateTimeField. */ @Override protected final boolean getConfiguredUpdateDisplayTextOnModify() { return false; } }
/** Configuration-related utilities. */ public final class ConfigurationUtility { private static final IScoutLogger LOG = ScoutLogManager.getLogger(ConfigurationUtility.class); private ConfigurationUtility() {} /** * Filters the given class array and sorts the remaining elements according to their {@link Order} * annotation. * * <p>By default, the method throws an {@link IllegalArgumentException} if one of the remaining * classes is not annotated by {@link Order}. The behavior can be switched off by setting the * system property <code>bsi.debug.innerclass.order</code> to an arbitrary value. * * @param classes * @param filter * @return * @throws IllegalArgumentException */ @SuppressWarnings("unchecked") public static <T> Class<T>[] sortFilteredClassesByOrderAnnotation( Class[] classes, Class<T> filter) { TreeMap<CompositeObject, Class> orderedClassesMap = new TreeMap<CompositeObject, Class>(); for (int i = 0; i < classes.length; i++) { if (filter.isAssignableFrom(classes[i])) { if (classes[i].isAnnotationPresent(Order.class)) { Order order = (Order) classes[i].getAnnotation(Order.class); orderedClassesMap.put(new CompositeObject(order.value(), i), classes[i]); } else { if (!classes[i].isAnnotationPresent(Replace.class)) { LOG.error("missing @Order annotation: " + classes[i].getName()); } orderedClassesMap.put(new CompositeObject(Double.MAX_VALUE, i), classes[i]); } } } return orderedClassesMap.values().toArray(new Class[orderedClassesMap.size()]); } /** @deprecated use {@link #sortByOrder(Collection)} instead. Will be removed in release 3.10. */ @Deprecated public static <T> Collection<T> sortByOrderAnnotation(Collection<T> list) { return sortByOrder(list); } /** * Sorts the elements according to their order: * * <ol> * <li>If an {@link Order} annotation is present, its {@link Order#value()} is used * <li>If a {@link Replace} annotation is present, the superclass' order is used * <li>If the object implements {@link IOrdered}, {@link IOrdered#getOrder()} is used * <li>Finally, the index in the original collection is used * </ol> * * @since 3.8.1 */ public static <T> Collection<T> sortByOrder(Collection<T> list) { if (list == null) { return null; } TreeMap<CompositeObject, T> sortMap = new TreeMap<CompositeObject, T>(); int index = 0; for (T element : list) { Class<?> c = element.getClass(); double order; Order orderAnnotation; while ((orderAnnotation = c.getAnnotation(Order.class)) == null && c.isAnnotationPresent(Replace.class)) { c = c.getSuperclass(); } if (orderAnnotation != null) { order = orderAnnotation.value(); } else if (element instanceof IOrdered) { order = ((IOrdered) element).getOrder(); } else { order = (double) index; } sortMap.put(new CompositeObject(order, index), element); index++; } return sortMap.values(); } /** * Filters the given class array and returns the first occurrence of an instantiable class of * filter * * @param classes * @param filter * @return first occurrence of filter, might be annotated with {@link InjectFieldTo} or {@link * Replace} */ @SuppressWarnings("unchecked") public static <T> Class<T> filterClass(Class[] classes, Class<T> filter) { for (Class c : classes) { if (filter.isAssignableFrom(c) && !Modifier.isAbstract(c.getModifiers())) { return c; } } return null; } /** * same as {@link #filterClass(Class[], Class)} but ignoring classes with {@link InjectFieldTo} * and {@link Replace} annotations * * @since 3.8.1 */ @SuppressWarnings("unchecked") public static <T> Class<T> filterClassIgnoringInjectFieldAnnotation( Class[] classes, Class<T> filter) { for (Class c : classes) { if (filter.isAssignableFrom(c) && !Modifier.isAbstract(c.getModifiers())) { if (!isInjectFieldAnnotationPresent(c)) { return c; } } } return null; } /** * Filters the given class array and returns all occurrences of instantiable classes of filter * * @param classes * @param filter * @return all occurrences of filter * @since 3.8.1 */ @SuppressWarnings("unchecked") public static <T> Class<T>[] filterClasses(Class[] classes, Class<T> filter) { ArrayList<Class<T>> list = new ArrayList<Class<T>>(); for (Class c : classes) { if (filter.isAssignableFrom(c) && !Modifier.isAbstract(c.getModifiers())) { list.add(c); } } return list.toArray(new Class[0]); } /** * same as {@link #filterClasses(Class[], Class)} but ignoring classes with {@link InjectFieldTo} * and {@link Replace} annotations * * @since 3.8.1 */ @SuppressWarnings("unchecked") public static <T> Class<T>[] filterClassesIgnoringInjectFieldAnnotation( Class[] classes, Class<T> filter) { ArrayList<Class<T>> list = new ArrayList<Class<T>>(); for (Class c : classes) { if (filter.isAssignableFrom(c) && !Modifier.isAbstract(c.getModifiers())) { if (!isInjectFieldAnnotationPresent(c)) { list.add(c); } } } return list.toArray(new Class[0]); } /** * same as {@link #filterClasses(Class[], Class)} but only accepting classes with {@link * InjectFieldTo} and {@link Replace} annotations * * @since 3.8.1 */ @SuppressWarnings("unchecked") public static <T> Class<T>[] filterClassesWithInjectFieldAnnotation( Class[] classes, Class<T> filter) { ArrayList<Class<T>> list = new ArrayList<Class<T>>(); for (Class c : classes) { if (filter.isAssignableFrom(c) && !Modifier.isAbstract(c.getModifiers())) { if (isInjectFieldAnnotationPresent(c)) { list.add(c); } } } return list.toArray(new Class[0]); } /** * @return Returns <code>true</code> if the given class is annotated by {@link InjectFieldTo} or * {@link Replace}. Otherwise <code>false</code>. * <p><b>Note:</b> This method throws a {@link NullPointerException} if the given class is * null. */ public static boolean isInjectFieldAnnotationPresent(Class<?> c) { return c.isAnnotationPresent(InjectFieldTo.class) || c.isAnnotationPresent(Replace.class); } /** get all declared classes (inner types) of the specified class and all its super classes */ public static Class[] getDeclaredPublicClasses(Class c) { return c.getClasses(); } public static <T> T newInnerInstance(Object instance, Class<T> innerClass) throws Exception { if (innerClass.getDeclaringClass() != null && (innerClass.getModifiers() & Modifier.STATIC) == 0) { Constructor<T> c = innerClass.getDeclaredConstructor(new Class[] {innerClass.getDeclaringClass()}); return c.newInstance(new Object[] {instance}); } else { return innerClass.newInstance(); } } /** @return true if the declared method is overwritten in implementationType */ public static boolean isMethodOverwrite( Class<?> declaringType, String methodName, Class[] parameterTypes, Class<?> implementationType) { try { Method declaredMethod; try { declaredMethod = declaringType.getDeclaredMethod(methodName, parameterTypes); } catch (NoSuchMethodException e) { LOG.error("cannot find declared method " + declaringType.getName() + "." + methodName, e); return false; } Class<?> c = implementationType; while (c != null && c != declaringType) { try { // check if method is avaliable c.getDeclaredMethod(declaredMethod.getName(), declaredMethod.getParameterTypes()); return true; } catch (NoSuchMethodException e) { // nop } // up c = c.getSuperclass(); } } catch (Throwable t) { LOG.error( "declaringType=" + declaringType + ", methodName=" + methodName + ", parameterTypes=" + parameterTypes + ", implementationType=" + implementationType, t); } return false; } /** * @return Returns the given objects enclosing container type, i.e the first class on the * enclosing classes path that is abstract or the outermost enclosing class. The latter is the * primary type. */ public static Class<?> getEnclosingContainerType(Object o) { if (o == null) { return null; } Class<?> c = o.getClass(); while (!Modifier.isAbstract(c.getModifiers()) && c.getEnclosingClass() != null) { c = c.getEnclosingClass(); } return c; } /** * Returns a new array without those classes, that are replaced by another class. The returned * array is a new instance, except there are no replacing classes. Replacing classes are annotated * with {@link Replace}. Replacing classes are reordered according to their nearest {@link Order} * annotation that is found up the type hierarchy. * * @param classes * @return * @since 3.8.2 */ @SuppressWarnings("unchecked") public static <T> Class<? extends T>[] removeReplacedClasses(Class<? extends T>[] classes) { Set<Class<? extends T>> replacingClasses = getReplacingLeafClasses(classes); if (replacingClasses.isEmpty()) { // there are no replacing classes -> return original array return classes; } // compute resulting list of ordered classes List<Class<? extends T>> list = new ArrayList<Class<? extends T>>(); for (Class<? extends T> c : classes) { list.add(c); } for (Class<? extends T> replacingClass : replacingClasses) { boolean reorder = !replacingClass.isAnnotationPresent(Order.class); boolean reordered = false; // handle transitive replacements Class<?> classToBeReplaced = replacingClass.getSuperclass(); while (classToBeReplaced.isAnnotationPresent(Replace.class)) { // reorder replacement if necessary if (reorder && !reordered && classToBeReplaced.isAnnotationPresent(Order.class)) { reordered = moveBefore(list, replacingClass, (Class<? extends T>) classToBeReplaced); } list.remove(classToBeReplaced); classToBeReplaced = classToBeReplaced.getSuperclass(); } // reorder replacement if necessary if (reorder && !reordered) { moveBefore(list, replacingClass, (Class<? extends T>) classToBeReplaced); } list.remove(classToBeReplaced); } return list.toArray(new Class[list.size()]); } /** * Computes a map based on the given classes that contains replaced classes pointing to their * replacing classes. This method never returns <code>null</code>. * * <p><b>Example:</b> Given the following two classes * * <pre> * public class A { * } * * @Replace * public class B extends A { * } * </pre> * * The invocation of <code>getReplacementMapping(new Class[] {B.class, String.class})</code> * returns a map containing <code><A.class, B.class></code>. * * @param classes * @return * @since 3.8.2 */ public static <T> Map<Class<?>, Class<? extends T>> getReplacementMapping( Class<? extends T>[] classes) { Set<Class<? extends T>> replacingClasses = getReplacingLeafClasses(classes); if (replacingClasses.isEmpty()) { // there are no replacing classes -> return original array return Collections.emptyMap(); } // compute resulting replacement mapping Map<Class<?>, Class<? extends T>> mappings = new HashMap<Class<?>, Class<? extends T>>(); for (Class<? extends T> c : replacingClasses) { Class<?> tmpClass = c; do { tmpClass = tmpClass.getSuperclass(); mappings.put(tmpClass, c); } while (tmpClass.isAnnotationPresent(Replace.class)); } return mappings; } /** * Computes the set of classes that are annotated with {@link Replace} and removes transitive * dependencies, so that the most specific classes are returned. * * <p><b>Example:</b> Given the following two classes * * <pre> * public class A { * } * * @Replace * public class B extends A { * } * </pre> * * The invocation of <code>getReplacingLeafClasses(new Class[] {A.class, B.class, String.class}) * </code> returns a set that contains <code>B.class</code> only. <code>String.class</code> is not * annotated with {@link Replace} and <code>A.class</code> is not a leaf replacement, but further * replaced by <code>B.class</code>. * * @param classes * @return Returns the set of replacing leaf classes or an empty set. * @since 3.8.2 */ public static <T> Set<Class<? extends T>> getReplacingLeafClasses(Class<? extends T>[] classes) { // gather all replacing and replaced classes (i.e. those annotated with @Replace and their super // classes) Set<Class<? extends T>> replacingClasses = new HashSet<Class<? extends T>>(); Set<Class<?>> replacedClasses = new HashSet<Class<?>>(); for (Class<? extends T> c : classes) { if (c.isAnnotationPresent(Replace.class)) { replacingClasses.add(c); Class<?> tmpClass = c; do { tmpClass = tmpClass.getSuperclass(); replacedClasses.add(tmpClass); } while (tmpClass.isAnnotationPresent(Replace.class)); } } if (replacingClasses.isEmpty()) { return Collections.emptySet(); } // remove transitive replacements (e.g. if A replaces B and B replaces C, A and B are replacing // classes but we are interested in A only) replacingClasses.removeAll(replacedClasses); return replacingClasses; } /** * Moves the given element before the reference element. Both are expected to be part of the given * list. If the reference element is not in the list, the list remains untouched. If the element * to move is not part of the list, it is added before the reference element. * * @param list * @param element * @param referenceElement * @return Returns <code>true</code> if the element has been moved or inserted. Otherwise <code> * false</code>. * @since 3.8.2 */ private static <T> boolean moveBefore(List<T> list, T element, T referenceElement) { int index = list.indexOf(referenceElement); if (index != -1) { list.remove(element); list.add(index, element); return true; } return false; } }
@ClassId("480ea07e-9cec-4591-ba73-4bb9aa45a60d") public abstract class AbstractImageField extends AbstractFormField implements IImageField { private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractImageField.class); private IImageFieldUIFacade m_uiFacade; private final EventListenerList m_listenerList = new EventListenerList(); private IContextMenu m_contextMenu; private double m_zoomDelta; private double m_panDelta; private double m_rotateDelta; public AbstractImageField() { this(true); } public AbstractImageField(boolean callInitializer) { super(callInitializer); } @Override protected int getConfiguredVerticalAlignment() { return 0; } @Override protected int getConfiguredHorizontalAlignment() { return 0; } @ConfigProperty(ConfigProperty.ICON_ID) @Order(300) protected String getConfiguredImageId() { return null; } @ConfigProperty(ConfigProperty.BOOLEAN) @Order(320) protected boolean getConfiguredAutoFit() { return false; } @ConfigProperty(ConfigProperty.DOUBLE) @Order(330) protected double getConfiguredZoomDelta() { return 1.25; } @Override @Order(190) @ConfigProperty(ConfigProperty.BOOLEAN) protected boolean getConfiguredFocusable() { return false; } @ConfigProperty(ConfigProperty.DOUBLE) @Order(340) protected double getConfiguredPanDelta() { return 10; } /** in degrees 0..360 */ @ConfigProperty(ConfigProperty.DOUBLE) @Order(350) protected double getConfiguredRotateDelta() { return 10; } @ConfigProperty(ConfigProperty.BOOLEAN) @Order(360) protected boolean getConfiguredScrollBarEnabled() { return false; } /** * Configures the drop support of this image field. * * <p>Subclasses can override this method. Default is {@code 0} (no drop support). * * @return {@code 0} for no support or one or more of {@link IDNDSupport#TYPE_FILE_TRANSFER}, * {@link IDNDSupport#TYPE_IMAGE_TRANSFER}, {@link IDNDSupport#TYPE_JAVA_ELEMENT_TRANSFER} or * {@link IDNDSupport#TYPE_TEXT_TRANSFER} (e.g. {@code TYPE_TEXT_TRANSFER | * TYPE_FILE_TRANSFER}). */ @ConfigProperty(ConfigProperty.DRAG_AND_DROP_TYPE) @Order(400) protected int getConfiguredDropType() { return 0; } /** * Configures the drag support of this image field. * * <p>Subclasses can override this method. Default is {@code 0} (no drag support). * * @return {@code 0} for no support or one or more of {@link IDNDSupport#TYPE_FILE_TRANSFER}, * {@link IDNDSupport#TYPE_IMAGE_TRANSFER}, {@link IDNDSupport#TYPE_JAVA_ELEMENT_TRANSFER} or * {@link IDNDSupport#TYPE_TEXT_TRANSFER} (e.g. {@code TYPE_TEXT_TRANSFER | * TYPE_FILE_TRANSFER}). */ @ConfigProperty(ConfigProperty.DRAG_AND_DROP_TYPE) @Order(410) protected int getConfiguredDragType() { return 0; } @ConfigOperation @Order(500) protected TransferObject execDragRequest() throws ProcessingException { return null; } @ConfigOperation @Order(510) protected void execDropRequest(TransferObject transferObject) throws ProcessingException {} protected List<Class<? extends IMenu>> getDeclaredMenus() { Class[] dca = ConfigurationUtility.getDeclaredPublicClasses(getClass()); List<Class<IMenu>> filtered = ConfigurationUtility.filterClasses(dca, IMenu.class); return ConfigurationUtility.removeReplacedClasses(filtered); } @Override public List<IKeyStroke> getContributedKeyStrokes() { return MenuUtility.getKeyStrokesFromMenus(getMenus()); } @Override protected void initConfig() { m_uiFacade = new P_UIFacade(); super.initConfig(); setImageTransform(new AffineTransformSpec()); setAutoFit(getConfiguredAutoFit()); setImageId(getConfiguredImageId()); setPanDelta(getConfiguredPanDelta()); setRotateDelta(getConfiguredRotateDelta()); setZoomDelta(getConfiguredZoomDelta()); setDragType(getConfiguredDragType()); setDropType(getConfiguredDropType()); setScrollBarEnabled(getConfiguredScrollBarEnabled()); // menus List<Class<? extends IMenu>> declaredMenus = getDeclaredMenus(); List<IMenu> contributedMenus = m_contributionHolder.getContributionsByClass(IMenu.class); OrderedCollection<IMenu> menus = new OrderedCollection<IMenu>(); for (Class<? extends IMenu> menuClazz : declaredMenus) { try { menus.addOrdered(ConfigurationUtility.newInnerInstance(this, menuClazz)); } catch (Exception e) { SERVICES .getService(IExceptionHandlerService.class) .handleException( new ProcessingException( "error creating instance of class '" + menuClazz.getName() + "'.", e)); } } menus.addAllOrdered(contributedMenus); try { injectMenusInternal(menus); } catch (Exception e) { LOG.error("error occured while dynamically contributing menus.", e); } new MoveActionNodesHandler<IMenu>(menus).moveModelObjects(); m_contextMenu = new FormFieldContextMenu<IImageField>(this, menus.getOrderedList()); m_contextMenu.setContainerInternal(this); } @Override protected void initFieldInternal() throws ProcessingException { super.initFieldInternal(); // init actions ActionUtility.initActions(getMenus()); } /** * Override this internal method only in order to make use of dynamic menus<br> * Used to add and/or remove menus<br> * To change the order or specify the insert position use {@link IMenu#setOrder(double)}. * * @param menus live and mutable collection of configured menus */ protected void injectMenusInternal(OrderedCollection<IMenu> menus) {} /* * Runtime */ /** model observer */ @Override public void addImageFieldListener(ImageFieldListener listener) { m_listenerList.add(ImageFieldListener.class, listener); } @Override public void removeImageFieldListener(ImageFieldListener listener) { m_listenerList.remove(ImageFieldListener.class, listener); } private void fireZoomRectangle(BoundsSpec r) { fireImageBoxEventInternal(new ImageFieldEvent(this, ImageFieldEvent.TYPE_ZOOM_RECTANGLE, r)); } private void fireAutoFit() { fireImageBoxEventInternal(new ImageFieldEvent(this, ImageFieldEvent.TYPE_AUTO_FIT)); } private void fireImageBoxEventInternal(ImageFieldEvent e) { EventListener[] a = m_listenerList.getListeners(ImageFieldListener.class); if (a != null) { for (int i = 0; i < a.length; i++) { ((ImageFieldListener) a[i]).imageFieldChanged(e); } } } @Override public Object getImage() { return propertySupport.getProperty(PROP_IMAGE); } @Override public void setImage(Object imgObj) { propertySupport.setProperty(PROP_IMAGE, imgObj); } @Override public String getImageId() { return propertySupport.getPropertyString(PROP_IMAGE_ID); } @Override public void setImageId(String imageId) { propertySupport.setPropertyString(PROP_IMAGE_ID, imageId); } @Override public IContextMenu getContextMenu() { return m_contextMenu; } @Override public List<IMenu> getMenus() { return getContextMenu().getChildActions(); } @Override public double getZoomDeltaValue() { return m_zoomDelta; } @Override public void setZoomDelta(double d) { m_zoomDelta = d; } @Override public double getPanDelta() { return m_panDelta; } @Override public void setPanDelta(double d) { m_panDelta = d; } @Override public double getRotateDelta() { return m_rotateDelta; } @Override public void setRotateDelta(double deg) { m_rotateDelta = deg; } @Override public void setRotateDeltaInRadians(double rad) { setRotateDelta(Math.toDegrees(rad)); } @Override public AffineTransformSpec getImageTransform() { return new AffineTransformSpec( (AffineTransformSpec) propertySupport.getProperty(PROP_IMAGE_TRANSFORM)); } @Override public void setImageTransform(AffineTransformSpec t) { propertySupport.setProperty(PROP_IMAGE_TRANSFORM, new AffineTransformSpec(t)); } @Override public BoundsSpec getAnalysisRectangle() { return (BoundsSpec) propertySupport.getProperty(PROP_ANALYSIS_RECTANGLE); } @Override public void setAnalysisRectangle(BoundsSpec rect) { propertySupport.setProperty(PROP_ANALYSIS_RECTANGLE, rect); } @Override public void setAnalysisRectangle(int x, int y, int w, int h) { setAnalysisRectangle(new BoundsSpec(x, y, w, h)); } @Override public boolean isAutoFit() { return propertySupport.getPropertyBool(PROP_AUTO_FIT); } @Override public void setAutoFit(boolean b) { propertySupport.setPropertyBool(PROP_AUTO_FIT, b); } @Override public boolean isScrollBarEnabled() { return propertySupport.getPropertyBool(PROP_SCROLL_BAR_ENABLED); } @Override public void setScrollBarEnabled(boolean b) { propertySupport.setPropertyBool(PROP_SCROLL_BAR_ENABLED, b); } @Override public void setDragType(int dragType) { propertySupport.setPropertyInt(PROP_DRAG_TYPE, dragType); } @Override public int getDragType() { return propertySupport.getPropertyInt(PROP_DRAG_TYPE); } @Override public void setDropType(int dropType) { propertySupport.setPropertyInt(PROP_DROP_TYPE, dropType); } @Override public int getDropType() { return propertySupport.getPropertyInt(PROP_DROP_TYPE); } @Override public byte[] getByteArrayValue() { Object value = getImage(); byte[] b = null; if (value instanceof byte[]) { b = (byte[]) value; } return b; } @Override public void doAutoFit() { fireAutoFit(); } @Override public void doZoomRectangle(int x, int y, int w, int h) { fireZoomRectangle(new BoundsSpec(x, y, w, h)); } @Override public void doPan(double dx, double dy) { AffineTransformSpec t = getImageTransform(); t.dx = dx; t.dy = dy; setImageTransform(t); } @Override public void doRelativePan(double dx, double dy) { AffineTransformSpec t = getImageTransform(); t.dx = t.dx + dx; t.dy = t.dy + dy; setImageTransform(t); } @Override public void doZoom(double fx, double fy) { AffineTransformSpec t = getImageTransform(); t.sx = fx; t.sy = fy; setImageTransform(t); } @Override public void doRelativeZoom(double fx, double fy) { AffineTransformSpec t = getImageTransform(); t.sx = t.sx * fx; t.sy = t.sy * fy; setImageTransform(t); } @Override public void doRotate(double angle) { AffineTransformSpec t = getImageTransform(); t.angle = angle; setImageTransform(t); } @Override public void doRelativeRotate(double angleInDegrees) { AffineTransformSpec t = getImageTransform(); t.angle = t.angle + Math.toRadians(angleInDegrees); setImageTransform(t); } /* * UI accessible */ @Override public IImageFieldUIFacade getUIFacade() { return m_uiFacade; } private class P_UIFacade implements IImageFieldUIFacade { @Override public void setImageTransformFromUI(AffineTransformSpec t) { setImageTransform(t); } @Override public TransferObject fireDragRequestFromUI() { TransferObject t = null; try { t = interceptDragRequest(); } catch (ProcessingException e) { LOG.warn(null, e); } return t; } @Override public void fireDropActionFromUi(TransferObject scoutTransferable) { try { interceptDropRequest(scoutTransferable); } catch (ProcessingException e) { LOG.warn(null, e); } } } // end private class protected final TransferObject interceptDragRequest() throws ProcessingException { List<? extends IFormFieldExtension<? extends AbstractFormField>> extensions = getAllExtensions(); ImageFieldDragRequestChain chain = new ImageFieldDragRequestChain(extensions); return chain.execDragRequest(); } protected final void interceptDropRequest(TransferObject transferObject) throws ProcessingException { List<? extends IFormFieldExtension<? extends AbstractFormField>> extensions = getAllExtensions(); ImageFieldDropRequestChain chain = new ImageFieldDropRequestChain(extensions); chain.execDropRequest(transferObject); } protected static class LocalImageFieldExtension<OWNER extends AbstractImageField> extends LocalFormFieldExtension<OWNER> implements IImageFieldExtension<OWNER> { public LocalImageFieldExtension(OWNER owner) { super(owner); } @Override public TransferObject execDragRequest(ImageFieldDragRequestChain chain) throws ProcessingException { return getOwner().execDragRequest(); } @Override public void execDropRequest(ImageFieldDropRequestChain chain, TransferObject transferObject) throws ProcessingException { getOwner().execDropRequest(transferObject); } } @Override protected IImageFieldExtension<? extends AbstractImageField> createLocalExtension() { return new LocalImageFieldExtension<AbstractImageField>(this); } }
public abstract class AbstractMemoryPolicy implements IMemoryPolicy { private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractMemoryPolicy.class); public static class SearchFormState { final String formContentXml; final SearchFilter searchFilter; public SearchFormState(String xml, SearchFilter filter) { formContentXml = xml; searchFilter = filter; } } private boolean m_active; private final WeakHashMap<IForm, String> m_formToIdentifierMap; private final WeakHashMap<ITable, String> m_tableToIdentifierMap; private final FormListener m_formListener = new FormListener() { @Override public void formChanged(FormEvent e) throws ProcessingException { // auto-detach if (!m_active) { e.getForm().removeFormListener(m_formListener); return; } String id = m_formToIdentifierMap.get(e.getForm()); if (id != null) { try { handlePageFormEvent(e, id); } catch (Throwable t) { LOG.warn("page form event " + e, t); } } } }; private final TableColumnFilterListener m_tableColumnFilterListener = new TableColumnFilterListener() { @Override public void tableColumnFilterChanged(TableColumnFilterEvent e) throws ProcessingException { if (!m_active) { e.getColumnFilterManager().removeListener(m_tableColumnFilterListener); return; } String id = m_tableToIdentifierMap.get(e.getTable()); if (id != null) { try { handleTableFilterEvent(e, id); } catch (Throwable t) { LOG.warn("table filter event " + e, t); } } } }; public AbstractMemoryPolicy() { m_formToIdentifierMap = new WeakHashMap<IForm, String>(); m_tableToIdentifierMap = new WeakHashMap<ITable, String>(); } @Override public void addNotify() { m_active = true; } @Override public void removeNotify() { m_active = false; } /** Attaches listener on page contents */ @Override public void pageCreated(IPage p) throws ProcessingException { if (p.getOutline() instanceof AbstractPageField.SimpleOutline) { return; } if (p instanceof IPageWithTable) { IPageWithTable<? extends ITable> pt = (IPageWithTable<?>) p; ITable table = pt.getTable(); if (table != null) { String pageTableIdentifier = registerPageTable(pt, table); if (pageTableIdentifier != null) { loadColumnFilterState(table, pageTableIdentifier); } } } } @Override public void pageSearchFormStarted(IPageWithTable<?> p) throws ProcessingException { if (p.getOutline() instanceof AbstractPageField.SimpleOutline) { return; } IForm f = p.getSearchFormInternal(); if (f != null) { String pageFormIdentifier = registerPageForm(p, f); if (f.isFormOpen()) { loadSearchFormState(f, pageFormIdentifier); } } } /** @return the identifier for the page form */ protected String registerPageForm(IPage p, IForm f) { String id = createUniqueIdForPage(p, f); m_formToIdentifierMap.put(f, id); f.removeFormListener(m_formListener); f.addFormListener(m_formListener); return id; } /** * @return the identifier for the page table or <code>null</code> if the table does not have a * column filter manager. */ protected String registerPageTable(IPage p, ITable t) { if (t.getColumnFilterManager() == null) { return null; } String id = createUniqueIdForPage(p, t); m_tableToIdentifierMap.put(t, id); t.getColumnFilterManager().removeListener(m_tableColumnFilterListener); t.getColumnFilterManager().addListener(m_tableColumnFilterListener); return id; } protected String createUniqueIdForPage(IPage p, Object o) { if (p == null) { return null; } StringBuilder builder = new StringBuilder(); createIdForPage(builder, p, o); IPage page = p.getParentPage(); while (page != null) { createIdForPage(builder, page, null); page = page.getParentPage(); } CRC32 crc = new CRC32(); crc.update(builder.toString().getBytes()); return "" + crc.getValue(); } private void createIdForPage(StringBuilder b, IPage page, Object o) { b.append("/"); b.append(page.getClass().getName()); if (page.getUserPreferenceContext() != null) { b.append("/"); b.append(page.getUserPreferenceContext()); } if (o != null) { b.append("/"); b.append(o.getClass().getName()); } FastBeanInfo pi = new FastBeanInfo(page.getClass(), page.getClass().getSuperclass()); for (FastPropertyDescriptor prop : pi.getPropertyDescriptors()) { if (prop.getReadMethod() != null && (Date.class.isAssignableFrom(prop.getPropertyType()) || Number.class.isAssignableFrom(prop.getPropertyType()) || String.class.isAssignableFrom(prop.getPropertyType()) || long.class.isAssignableFrom(prop.getPropertyType()))) { // only accept Numbers, Strings or Dates try { b.append("/"); b.append(prop.getName()); b.append("="); b.append(prop.getReadMethod().invoke(page, new Object[0])); } catch (Exception e) { e.printStackTrace(); // nop - ignore this property } } } } protected void handlePageFormEvent(FormEvent e, String pageFormIdentifier) throws ProcessingException { switch (e.getType()) { case FormEvent.TYPE_LOAD_COMPLETE: { // store form state since it was probably reset storeSearchFormState(e.getForm(), pageFormIdentifier); break; } case FormEvent.TYPE_STORE_AFTER: { storeSearchFormState(e.getForm(), pageFormIdentifier); break; } } } protected void loadSearchFormState(IForm f, String pageFormIdentifier) throws ProcessingException { // nop } protected void storeSearchFormState(IForm f, String pageFormIdentifier) throws ProcessingException { // nop } protected void handleTableFilterEvent(TableColumnFilterEvent e, String id) throws ProcessingException { switch (e.getType()) { case TableColumnFilterEvent.TYPE_FILTER_ADDED: case TableColumnFilterEvent.TYPE_FILTER_CHANGED: case TableColumnFilterEvent.TYPE_FILTER_REMOVED: case TableColumnFilterEvent.TYPE_FILTERS_RESET: storeColumnFilterState(e.getTable(), id); break; } } protected void storeColumnFilterState(ITable t, String pageTableIdentifier) throws ProcessingException { // nop } protected void loadColumnFilterState(ITable t, String pageTableIdentifier) throws ProcessingException { // nop } @Override public void afterOutlineSelectionChanged(final IDesktop desktop) {} @Override public void beforeTablePageLoadData(IPageWithTable<?> page) {} @Override public void afterTablePageLoadData(IPageWithTable<?> page) {} @Override public String toString() { return getClass().getSimpleName(); } }
/** @author mzi */ public class MqttService extends AbstractService implements IMqttService, MqttCallback { private static IScoutLogger s_logger = ScoutLogManager.getLogger(MqttService.class); private IClientSession m_session; private MqttClient m_mqttClient = null; private boolean m_isConnected = false; @Override public void setup(String broker, String clientId) throws ProcessingException { try { MemoryPersistence persistence = new MemoryPersistence(); m_session = ClientSession.get(); m_mqttClient = new MqttClient(broker, clientId, persistence); m_mqttClient.setCallback(this); } catch (Exception e) { throw new ProcessingException(TEXTS.get("MqttClientCreateException"), e); } } @Override public void connect( String userName, String password, Boolean clearSession, Integer connectionTimeout, String lwtTopic, String lwtMessage, Integer qos, Boolean lwtRetained) throws ProcessingException { if (m_mqttClient == null) { throw new ProcessingException("no mqtt client instance available, call method 'setup' first"); } try { MqttConnectOptions options = getConnectOptions( userName, password, clearSession, connectionTimeout, lwtTopic, lwtMessage, qos, lwtRetained); m_mqttClient.connect(options); m_isConnected = true; } catch (Exception e) { throw new ProcessingException("an exception ocurred while connecting to the mqtt broker", e); } } private MqttConnectOptions getConnectOptions( String userName, String password, Boolean clearSession, Integer connectionTimeout, String lwtTopic, String lwtMessage, Integer lwtQos, Boolean lwtRetained) { MqttConnectOptions connectOpts = new MqttConnectOptions(); if (!StringUtility.isNullOrEmpty(userName)) { connectOpts.setUserName(userName); if (!StringUtility.isNullOrEmpty(password)) { connectOpts.setPassword(password.toCharArray()); } } if (clearSession != null) { connectOpts.setCleanSession(clearSession); } if (connectionTimeout != null) { connectOpts.setConnectionTimeout(connectionTimeout); } if (!StringUtility.isNullOrEmpty(lwtTopic) && !StringUtility.isNullOrEmpty(lwtMessage)) { connectOpts.setWill( lwtTopic, lwtMessage.getBytes(), NumberUtility.nvl(lwtQos, 1), BooleanUtility.nvl(lwtRetained, false)); } return connectOpts; } @Override public void connectionLost(Throwable t) { s_logger.error("connection to mqtt broker lost. reason: " + t); m_isConnected = false; if (m_session != null) { new ClientJob("mqtt connection lost", m_session, true) { @Override protected void runVoid(IProgressMonitor monitor) throws Exception { MessageHandlingService service = SERVICES.getService(MessageHandlingService.class); service.handleDisconnect(); } }.schedule(); } else { s_logger.error("client session is null"); } } @Override public void deliveryComplete(IMqttDeliveryToken t) { s_logger.info("delivery of mqtt message completed. deliveryToken=" + t); } @Override public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception { s_logger.info( "mqtt message arrived. message " + topic + ":'" + new String(mqttMessage.getPayload()) + "' qos=" + mqttMessage.getQos() + " retained=" + mqttMessage.isRetained()); final String message = new String(mqttMessage.getPayload()); final int qos = mqttMessage.getQos(); final boolean retained = mqttMessage.isRetained(); final Date received = new Date(); if (m_session != null) { // prevent blocking of modal thread new ClientAsyncJob("mqtt message arrived (async wrapper)", m_session, true) { @Override protected void runVoid(IProgressMonitor monitor) throws Exception { // implement ui changes in a sync job new ClientSyncJob("mqtt message arrived", m_session) { @Override protected void runVoid(IProgressMonitor monitor1) throws Throwable { MessageHandlingService service = SERVICES.getService(MessageHandlingService.class); service.handleMessage(topic, message, qos, retained, received); } }.schedule(); } }.schedule(); } else { s_logger.error("client session is null"); } } @Override public void disconnect() throws ProcessingException { checkConnection(); try { m_mqttClient.disconnect(); m_isConnected = false; } catch (MqttException e) { throw new ProcessingException(TEXTS.get("mqttException"), e); } } @Override public void publish(String topic, String content, Integer qos, Boolean retained) throws ProcessingException { checkConnection(); try { MqttMessage message = new MqttMessage(content.getBytes()); if (qos != null) { message.setQos(qos); } if (retained != null) { message.setRetained(retained); } m_mqttClient.publish(topic, message); } catch (Exception e) { throw new ProcessingException(TEXTS.get("publishError"), e); } s_logger.info("message " + topic + ":'" + content + "' successfully published"); } @Override public void subscribe(String topicFilter, Integer qos) throws ProcessingException { checkConnection(); try { if (qos == null) { m_mqttClient.subscribe(topicFilter); } else { m_mqttClient.subscribe(topicFilter, qos); } } catch (Exception e) { throw new ProcessingException(TEXTS.get("subscribeError"), e); } s_logger.info("topic " + topicFilter + "' successfully subscribed"); } @Override public void unsubscribe(String topicFilter) throws ProcessingException { checkConnection(); try { m_mqttClient.unsubscribe(topicFilter); } catch (Exception e) { throw new ProcessingException(TEXTS.get("unsubscribeError"), e); } } private void checkConnection() throws ProcessingException { if (m_mqttClient == null) { throw new ProcessingException(TEXTS.get("noClient")); } if (!m_mqttClient.isConnected()) { throw new ProcessingException(TEXTS.get("noConnection")); } } @Override public boolean isConnected() throws ProcessingException { return m_isConnected; } }
public class UiDecoration implements IUiDecoration { private static IScoutLogger LOG = ScoutLogManager.getLogger(UiDecoration.class); private String m_mandatoryFieldBackgroundColor; private int m_mandatoryStarMarkerPosition; private String m_mandatoryLabelTextColor; private FontSpec m_mandatoryLabelFont; private int m_dialogMinWidth; private int m_dialogMinHeight; private int m_formFieldActivationButtonHeight; private int m_formFieldActivationButtonWidth; private int m_formFieldActivationButtonWithMenuWidth; private int m_formFieldLabelWidth; private int m_logicalGridLayoutDefaultColumnWidth; private int m_logicalGridLayoutHorizontalGap; private int m_logicalGridLayoutVerticalGap; private int m_logicalGridLayoutRowHeight; private int m_processButtonHeight; private int m_processButtonMinWidth; private int m_processButtonMaxWidth; private String m_colorForegroundDisabled; private int m_messageBoxMinWidth = 400; private int m_messageBoxMinHeight = 100; private boolean m_tableMouseMoveSelectionSupportEnabled; private boolean m_tableMultilineTooltipSupportEnabled; /** one of SWT.RIGHT SWT.LEFT SWT.CENTER */ private int m_formFieldLabelAlignment = SWT.RIGHT; @Override public int getDialogMinWidth() { return m_dialogMinWidth; } public void setDialogMinWidth(int dialogMinWidth) { m_dialogMinWidth = dialogMinWidth; } @Override public int getDialogMinHeight() { return m_dialogMinHeight; } public void setDialogMinHeight(int dialogMinHeight) { m_dialogMinHeight = dialogMinHeight; } @Override public int getProcessButtonHeight() { return m_processButtonHeight; } public void setProcessButtonHeight(int processButtonHeight) { m_processButtonHeight = processButtonHeight; } @Override public int getProcessButtonMinWidth() { return m_processButtonMinWidth; } public void setProcessButtonMinWidth(int processButtonMinWidth) { m_processButtonMinWidth = processButtonMinWidth; } @Override public int getProcessButtonMaxWidth() { return m_processButtonMaxWidth; } public void setProcessButtonMaxWidth(int processButtonMaxWidth) { m_processButtonMaxWidth = processButtonMaxWidth; } @Override public int getFormFieldActivationButtonHeight() { return m_formFieldActivationButtonHeight; } public void setFormFieldActivationButtonHeight(int formFieldActivationButtonHeight) { m_formFieldActivationButtonHeight = formFieldActivationButtonHeight; } @Override public int getFormFieldActivationButtonWidth() { return m_formFieldActivationButtonWidth; } public void setFormFieldActivationButtonWidth(int formFieldActivationButtonWidth) { m_formFieldActivationButtonWidth = formFieldActivationButtonWidth; } @Override public int getFormFieldActivationButtonWithMenuWidth() { return m_formFieldActivationButtonWithMenuWidth; } public void setFormFieldActivationButtonWithMenuWidth( int formFieldActivationButtonWithMenuWidth) { m_formFieldActivationButtonWithMenuWidth = formFieldActivationButtonWithMenuWidth; } @Override public String getMandatoryFieldBackgroundColor() { return m_mandatoryFieldBackgroundColor; } public void setMandatoryFieldBackgroundColor(String mandatoryFieldBackgroundColor) { m_mandatoryFieldBackgroundColor = mandatoryFieldBackgroundColor; } @Override public int getMandatoryStarMarkerPosition() { return m_mandatoryStarMarkerPosition; } public void setMandatoryStarMarkerPosition(int mandatoryStarMarkerPosition) { m_mandatoryStarMarkerPosition = mandatoryStarMarkerPosition; } @Override public String getMandatoryLabelTextColor() { return m_mandatoryLabelTextColor; } public void setMandatoryLabelTextColor(String mandatoryLabelTextColor) { m_mandatoryLabelTextColor = mandatoryLabelTextColor; } @Override public FontSpec getMandatoryLabelFont() { return m_mandatoryLabelFont; } public void setMandatoryLabelFont(FontSpec mandatoryLabelFont) { m_mandatoryLabelFont = mandatoryLabelFont; } @Override public int getFormFieldLabelWidth() { return m_formFieldLabelWidth; } public void setFormFieldLabelWidth(int formFieldLabelWidth) { m_formFieldLabelWidth = formFieldLabelWidth; } @Override public int getLogicalGridLayoutDefaultColumnWidth() { return m_logicalGridLayoutDefaultColumnWidth; } public void setLogicalGridLayoutDefaultColumnWidth(int logicalGridLayoutDefaultColumnWidth) { m_logicalGridLayoutDefaultColumnWidth = logicalGridLayoutDefaultColumnWidth; } @Override public int getLogicalGridLayoutHorizontalGap() { return m_logicalGridLayoutHorizontalGap; } public void setLogicalGridLayoutHorizontalGap(int logicalGridLayoutHorizontalGap) { m_logicalGridLayoutHorizontalGap = logicalGridLayoutHorizontalGap; } @Override public int getLogicalGridLayoutVerticalGap() { return m_logicalGridLayoutVerticalGap; } public void setLogicalGridLayoutVerticalGap(int logicalGridLayoutVerticalGap) { m_logicalGridLayoutVerticalGap = logicalGridLayoutVerticalGap; } @Override public int getLogicalGridLayoutRowHeight() { return m_logicalGridLayoutRowHeight; } public void setLogicalGridLayoutRowHeight(int logicalGridLayoutRowHeight) { m_logicalGridLayoutRowHeight = logicalGridLayoutRowHeight; } @Override public String getColorForegroundDisabled() { return m_colorForegroundDisabled; } public void setColorForegroundDisabled(String colorForegroundDisabled) { m_colorForegroundDisabled = colorForegroundDisabled; } @Override public int getFormFieldLabelAlignment() { return m_formFieldLabelAlignment; } public void setFormFieldLabelAlignment(int propertyString) { m_formFieldLabelAlignment = propertyString; } @Override public int getMessageBoxMinWidth() { return m_messageBoxMinWidth; } public void setMessageBoxMinWidth(int messageBoxMinWidth) { m_messageBoxMinWidth = messageBoxMinWidth; } @Override public int getMessageBoxMinHeight() { return m_messageBoxMinHeight; } public void setMessageBoxMinHeight(int messageBoxMinHeight) { m_messageBoxMinHeight = messageBoxMinHeight; } public void setTableMouseMoveSelectionSupportEnabled( boolean tableMouseMoveSelectionSupportEnabled) { m_tableMouseMoveSelectionSupportEnabled = tableMouseMoveSelectionSupportEnabled; } @Override public boolean isTableMouseMoveSelectionSupportEnabled() { return m_tableMouseMoveSelectionSupportEnabled; } public void setTableMultilineTooltipSupportEnabled(boolean tableMultilineTooltipSupportEnabled) { m_tableMultilineTooltipSupportEnabled = tableMultilineTooltipSupportEnabled; } @Override public boolean isTableMultilineTooltipSupportEnabled() { return m_tableMultilineTooltipSupportEnabled; } }
public final class Base64Utility { private static final IScoutLogger LOG = ScoutLogManager.getLogger(Base64Utility.class); private Base64Utility() {} private static final char[] BYTE_TO_CHAR; private static final int[] CHAR_TO_BYTE; static { BYTE_TO_CHAR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); int[] charToByte = new int[128]; for (int i = 0; i < BYTE_TO_CHAR.length; i++) { charToByte[(int) BYTE_TO_CHAR[i]] = i; } CHAR_TO_BYTE = charToByte; } /** * Base-64 encodes the supplied block of data. Line wrapping is not applied on output. * * @param bytes The block of data that is to be Base-64 encoded. * @return A <code>String</code> containing the encoded data. */ public static String encode(byte[] bytes) { int length = bytes.length; if (length == 0) { return ""; } StringBuilder buffer = new StringBuilder((int) Math.ceil(length / 3d) * 4); int remainder = length % 3; length -= remainder; int block; int i = 0; while (i < length) { block = ((bytes[i++] & 0xff) << 16) | ((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff); buffer.append(BYTE_TO_CHAR[block >>> 18]); buffer.append(BYTE_TO_CHAR[(block >>> 12) & 0x3f]); buffer.append(BYTE_TO_CHAR[(block >>> 6) & 0x3f]); buffer.append(BYTE_TO_CHAR[block & 0x3f]); } if (remainder == 0) { return buffer.toString(); } if (remainder == 1) { block = (bytes[i] & 0xff) << 4; buffer.append(BYTE_TO_CHAR[block >>> 6]); buffer.append(BYTE_TO_CHAR[block & 0x3f]); buffer.append("=="); return buffer.toString(); } block = (((bytes[i++] & 0xff) << 8) | ((bytes[i]) & 0xff)) << 2; buffer.append(BYTE_TO_CHAR[block >>> 12]); buffer.append(BYTE_TO_CHAR[(block >>> 6) & 0x3f]); buffer.append(BYTE_TO_CHAR[block & 0x3f]); buffer.append("="); return buffer.toString(); } /** * Decodes the supplied Base-64 encoded string. * * @param string The Base-64 encoded string that is to be decoded. * @return A <code>byte[]</code> containing the decoded data block. */ public static byte[] decode(String string) { int length = string == null ? 0 : string.length(); if (length == 0) { return new byte[0]; } P_Base64InputStream is = new P_Base64InputStream(string); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int c1, c2, c3, c4; try { c1 = is.read(); c2 = is.read(); c3 = is.read(); c4 = is.read(); while (c1 >= 0 || c2 >= 0 || c3 >= 0 || c4 >= 0) { int block; block = ((c1 != -1 ? CHAR_TO_BYTE[c1] : -1) & 0xff) << 18 | ((c2 != -1 ? CHAR_TO_BYTE[c2] : -1) & 0xff) << 12 | ((c3 != -1 ? CHAR_TO_BYTE[c3] : -1) & 0xff) << 6 | ((c4 != -1 ? CHAR_TO_BYTE[c4] : -1) & 0xff); buffer.write((byte) (block >>> 16)); if (c3 != -1) { buffer.write((byte) ((block >>> 8) & 0xff)); } if (c4 != -1) { buffer.write((byte) (block & 0xff)); } c1 = is.read(); c2 = is.read(); c3 = is.read(); c4 = is.read(); } } catch (IOException e) { LOG.error("IOException in Base64Utility.decode()", e); return new byte[0]; } finally { try { if (is != null) { is.close(); } } catch (IOException e) { LOG.warn("P_Base64InputStream couldn't be closed.", e); } } return buffer.toByteArray(); } private static class P_Base64InputStream extends InputStream { private final String m_buffer; private final int m_count; private int m_pos = 0; public P_Base64InputStream(String base64String) { m_buffer = base64String; m_count = base64String.length(); } @Override public int read() throws IOException { while (m_pos < m_count) { char ch = m_buffer.charAt(m_pos++); if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch == '+') || (ch == '/')) { return (ch & 0xFF); } } return -1; } } }
class ViewSplit { private static final IScoutLogger LOG = ScoutLogManager.getLogger(ViewSplit.class); private Set<CellSplit> m_cellSplits; private Set<ViewElement> m_leftViews; private Set<ViewElement> m_rightViews; ViewSplit(Set<CellSplit> cellSplits) { m_cellSplits = cellSplits; } public ViewSplit( Set<CellSplit> cellSplits, Set<ViewElement> leftViews, Set<ViewElement> rightViews) { m_cellSplits = cellSplits; m_leftViews = leftViews; m_rightViews = rightViews; } public Set<CellSplit> getCellSplits() { return m_cellSplits; } public Set<ViewElement> getLeftViews() { return m_leftViews; } public Set<ViewElement> getRightViews() { return m_rightViews; } public int getLocation() { int i = 0; for (CellSplit s : m_cellSplits) { i += s.getLocation(); } i = i / Math.max(1, m_cellSplits.size()); return i; } public void setLocation(int loc) { if (!isFixed()) { for (CellSplit s : m_cellSplits) { s.setLocation(loc); } } } /** * left=top, right=bottom * * @return amount that was effectively moved */ public int move(int delta, boolean force) { if (delta != 0) { int limit; if (force) { limit = Math.abs(delta); } else { boolean right = delta > 0; // check min/max sizes int leftSideLimit = 0; int rightSideLimit = 0; if (!isFixed()) { leftSideLimit = 10240; rightSideLimit = 10240; for (ViewElement v : m_leftViews) { int[] /* distance-to-min,distance-to-max*/ bounds = getResizeDistances(v, isRowSplit() ? v.top : v.left); int distanceToMin = bounds[0]; int distanceToMax = bounds[1]; if (right) { // use distanceToMax leftSideLimit = Math.min(leftSideLimit, distanceToMax); } else { // use negative distanceToMin leftSideLimit = Math.min(leftSideLimit, -distanceToMin); } } for (ViewElement v : m_rightViews) { int[] /* distance-to-min,distance-to-max*/ bounds = getResizeDistances(v, isRowSplit() ? v.bottom : v.right); int distanceToMin = bounds[0]; int distanceToMax = bounds[1]; if (right) { // use negative distanceToMin rightSideLimit = Math.min(rightSideLimit, -distanceToMin); } else { // use distanceToMax rightSideLimit = Math.min(rightSideLimit, distanceToMax); } } } limit = Math.min(leftSideLimit, rightSideLimit); if (limit > 0) { if (right) { if (delta > limit) { delta = limit; } } else { if (delta < -limit) { delta = -limit; } } setLocation(getLocation() + delta); return delta; } else { return 0; } } setLocation(getLocation() + delta); return delta; } return 0; } public boolean isFixed() { for (CellSplit s : m_cellSplits) { if (s.isFixed()) { return true; } } return false; } public boolean isRowSplit() { for (CellSplit s : m_cellSplits) { if (s.isRowSplit()) { return true; } } return false; } private int[] /*distance-to-min,distance-to-max*/ getResizeDistances( ViewElement v, ViewSplit oppositeSplit) { Component comp = v.getFrame(); if (comp == null || oppositeSplit == null) { return new int[] {0, 0}; } Dimension[] d = SwingLayoutUtility.getValidatedSizes(comp); /* * ticket 90942, detail pane initially only has 20px height * The size of the JInternalFrame is irrelevant and may be different than the effective split size, * therefore strictly use the current size of the split distance * [old inaccurate: Dimension s = comp.getSize();] */ int splitSize = Math.abs(oppositeSplit.getLocation() - this.getLocation()); if (isRowSplit()) { return getResizeDistances(d[0].height, splitSize, d[2].height); } else { return getResizeDistances(d[0].width, splitSize, d[2].width); } } private int[] /* distance-to-min,distance-to-max */ getResizeDistances( int min, int value, int max) { if (value < min) { return new int[] {0, max - value}; } else if (value > max) { return new int[] {min - value, 0}; } else { return new int[] {min - value, max - value}; } } @Override public String toString() { return getClass().getSimpleName() + "[" + (isFixed() ? "fixed " : "") + getLocation() + "]"; } }
/** @author mzi */ public class BugzillaHtmlFetcher implements IBugFetcher { private static final IScoutLogger LOG = ScoutLogManager.getLogger(BugzillaHtmlFetcher.class); private String m_criteria = null; private String m_assignee = null; private String m_product = null; private int m_maxNumberOfBugs = 5; @Override public void setQueryCriteria(String criteria) { m_criteria = criteria; } @Override public String getQueryCriteria() { return m_criteria; } @Override public void setAssignee(String assignee) { m_assignee = assignee; } @Override public String getAssignee() { return m_assignee; } @Override public void setProduct(String product) { m_product = product; } @Override public String getProduct() { return m_product; } @Override public void setMaxNumberOfBugs(int bugs) { m_maxNumberOfBugs = bugs; } @Override public int getMaxNumberOfBugs() { return m_maxNumberOfBugs; } @Override public List<IBug> fetchBugs() throws ProcessingException { List<IBug> bugs = new ArrayList<IBug>(); String url = buildQueryUrl(); Element bugTable = getBugTableElement(url, 10000); Elements bugElements = getBugElements(bugTable); int i = 0; for (Element e : bugElements) { if (i++ >= getMaxNumberOfBugs()) break; bugs.add(createBugFromElement(e, i)); } return bugs; } private String buildQueryUrl() { String url = getQueryCriteria(); String assignee = StringUtility.nvl(getAssignee(), "").trim(); String product = StringUtility.nvl(getProduct(), "").trim(); if (assignee.length() > 0) { LOG.info("assignee='" + assignee + "'"); url += "&emailtype1=substring&emailassigned_to1=1&email1=" + assignee; } if (product.length() > 0) { LOG.info("product='" + product + "'"); url += "&product=" + product; } LOG.info("using query url='" + url + "'"); return url; } private Element getBugTableElement(String url, int timeout) throws ProcessingException { Document doc = null; if (StringUtility.isNullOrEmpty(url)) { throw new ProcessingException( "No bugzilla base query url provided, check your config.ini file"); } try { doc = Jsoup.parse(new URL(url), timeout); if (doc == null) throw new ProcessingException("Empty document received, check your connection"); } catch (Exception e) { throw new ProcessingException( "Exception ", "check your connection and url: '" + url + "'", e); } return doc.getElementsByClass("bz_buglist").first(); } private Elements getBugElements(Element bugTable) { if (bugTable == null) return new Elements(); else return bugTable.getElementsByClass("bz_bugitem"); } /** * columns are parsed out or bugzilla html response. this implies that column list provided in the * criteria url and the parsing implemented in this method must correspond. see the config.ini * entry * org.eclipsescout.demo.ibug.server.services.DesktopService#criteria=https://bugs.eclipse.org/bugs/... */ private IBug createBugFromElement(Element e, int i) { IBug bug = new BugzillaBug(); Elements columnElements = e.getElementsByTag("td"); bug.setId(getColumnTextContent(columnElements, 0)); bug.setSeverety(getColumnTextContent(columnElements, 1)); bug.setPriority(getColumnTextContent(columnElements, 2)); bug.setTargetMilestone(getColumnTextContent(columnElements, 3)); bug.setStatus(getColumnTextContent(columnElements, 4)); bug.setResolution(getColumnTextContent(columnElements, 5)); bug.setComponent(getColumnTextContent(columnElements, 6)); bug.setAssignee(getColumnTextContent(columnElements, 7)); bug.setSummary(getColumnTextContent(columnElements, 8)); bug.setChanged(getColumnTextContent(columnElements, 9)); bug.setSortValue(i); return bug; } private String getColumnTextContent(Elements rowElements, int i) { Element content = rowElements.get(i); Element a = content.getElementsByTag("a").first(); Element span = content.getElementsByTag("span").first(); StringBuffer text = new StringBuffer(); text.append(content.ownText()); if (a != null) text.append(a.ownText()); if (span != null) text.append(span.ownText()); return text.toString(); } }
/** * * * <h3>BrowserSupport</h3> * * adding hyperlink callback support as in normal swt to the rwt browser * * <p>Adding support for registering/unregistering (publishing) local resources. * * @author imo * @since 3.8.0 */ public class BrowserExtension { private static final IScoutLogger LOG = ScoutLogManager.getLogger(BrowserExtension.class); private static final Pattern LOCAL_URL_PATTERN = Pattern.compile( "(['\"])(http://local[?/][^'\"]*)(['\"])", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); private final Browser m_browser; private final HashMap<String, String> m_hyperlinkMap; private final String m_serviceHandlerId; private ServiceHandler m_serviceHandler; private ServerPushSession m_pushSession; // private HashSet<String> m_tempFileNames = new HashSet<String>(); public BrowserExtension(Browser b) { m_browser = b; m_hyperlinkMap = new HashMap<String, String>(); m_serviceHandlerId = UUID.randomUUID().toString(); } /** @return the unique {@link UUID} serviceHandlerId */ public String getServiceHandlerId() { return m_serviceHandlerId; } // TODO RAP 2.0 migration - old code // private String getUiCallbackId() { // return getClass().getName() + "" + hashCode(); // } public void attach() { if (m_serviceHandler == null) { // TODO RAP 2.0 migration - old code // old code UICallBack.activate(getUiCallbackId()); m_pushSession = new ServerPushSession(); m_pushSession.start(); m_serviceHandler = new ServiceHandler() { @Override public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String localUrl = m_hyperlinkMap.get(request.getParameter("p")); if (localUrl == null) { return; } fireLocationChangedEvent(localUrl); } }; RWT.getServiceManager().registerServiceHandler(m_serviceHandlerId, m_serviceHandler); } } public void detach() { // TODO RAP 2.0 migration - old code // old code UICallBack.deactivate(getUiCallbackId()); m_pushSession.stop(); clearLocalHyperlinkCache(); clearResourceCache(); if (m_serviceHandler != null) { m_serviceHandler = null; RWT.getServiceManager().unregisterServiceHandler(m_serviceHandlerId); } } /** * Adds a text resource that is encoded with the given <code>charset</code>. * * <p>By specifying an <code>option</code> other than <code>NONE</code> the resource will be * versioned and/or compressed. As compressing is only intended for resources that contain * JavaScript, versioning might be useful for other resources as well. When versioning is enabled * a version number is appended to the resources' name which is derived from its content. * * <p> * * @param content the content of the resource to add. * @return the web url of the resource valid for calls from outside */ public String addResource(String name, InputStream content) { name = name.replaceAll("\\\\", "/"); if (name == null || name.length() == 0) { return null; } if (!name.startsWith("/")) { name = "/" + name; } String uniqueName = m_serviceHandlerId + name; m_tempFileNames.add(uniqueName); ResourceManager resourceManager = RWT.getResourceManager(); resourceManager.register(uniqueName, content); return resourceManager.getLocation(uniqueName); } public void clearResourceCache() { ResourceManager resourceManager = RWT.getResourceManager(); try { for (String name : m_tempFileNames) { resourceManager.unregister(name); } } finally { m_tempFileNames.clear(); } } /** * @param html replaces all http://local/... urls by a ajax callback with a {@link LocationEvent} * in html text * @param childDepth when the document is inside a iframe or thelike, then childDepth is 1, if it * is in addition inside an embed tag (such as svg), then childDepth is 2. */ public String adaptLocalHyperlinks(String html, int childDepth) { String p; if (childDepth <= 0) { p = "this"; } else { p = "parent"; for (int i = 1; i < childDepth; i++) { p = "parent." + p; } } return rewriteLocalHyperlinks(html, p, m_serviceHandlerId, m_hyperlinkMap); } public void clearLocalHyperlinkCache() { m_hyperlinkMap.clear(); } private void fireLocationChangedEvent(final String location) { m_browser .getDisplay() .asyncExec( new Runnable() { @Override public void run() { try { Constructor<?> c = LocationEvent.class.getDeclaredConstructor(Object.class); c.setAccessible(true); // send changing LocationEvent event = (LocationEvent) c.newInstance(new Event()); event.location = location; event.top = true; // send changing final Listener[] locationChangingListeners = m_browser.getListeners(EventTypes.LOCALTION_CHANGING); if (locationChangingListeners != null) { for (Listener l : locationChangingListeners) { if (l instanceof LocationListener) { ((LocationListener) l).changing(event); } } } // send changed final Listener[] locationChangedListeners = m_browser.getListeners(EventTypes.LOCALTION_CHANGED); if (locationChangedListeners != null) { for (Listener l : locationChangedListeners) { if (l instanceof LocationListener) { ((LocationListener) l).changed(event); } } } } catch (Throwable t) { // nop } } }); } /** * Replace all href="http://local/... references in the html file and replace by an ajax call. * * @param html * @param rwtServiceHandler is called with the parameter "p" containing the local url key to the * generatedMapping * @param generatedMappings is being filled up with the generated mappings * @return the rewritten html */ private static String rewriteLocalHyperlinks( String html, String ajaxParentContext, String rwtServiceHandler, Map<String /*externalKey*/, String /*url*/> generatedMappings) { if (html == null) { return html; } StringBuilder buf = new StringBuilder(); Matcher m = LOCAL_URL_PATTERN.matcher(html); int nextFind = 0; while (m.find(nextFind)) { String localUrl = m.group(2); String externalKey = "" + generatedMappings.size(); StringBuilder urlBuf = new StringBuilder(); urlBuf.append("?"); urlBuf.append("nocache='+new Date().getTime()+'"); urlBuf.append("&"); urlBuf.append("custom_service_handler"); urlBuf.append("="); urlBuf.append(rwtServiceHandler); urlBuf.append("&"); urlBuf.append("p"); urlBuf.append("="); urlBuf.append(externalKey); String encodedURL = RWT.getResponse().encodeURL(urlBuf.toString()); String callableURL = "javascript:a=" + ajaxParentContext + ".qx.net.HttpRequest.create();a.open('GET','" + encodedURL + "',true);a.send(null);"; buf.append(html.substring(nextFind, m.start())); buf.append(m.group(1)); buf.append(callableURL); buf.append(m.group(3)); // register generatedMappings.put(externalKey, localUrl); // next nextFind = m.end(); } if (nextFind == 0) { return html; } if (nextFind < html.length()) { buf.append(html.substring(nextFind)); } return buf.toString(); } }
/** * Dynamic code service for testing purposes. Arbitrary code types can be registered dynamically. * Consumers must register and remove the service themselves. * * <p><b>Example</b>: * * <pre> * List<ServiceRegistration> reg = TestingUtility.registerServices(Activator.getDefault().getBundle(), 1000, new TestingCodeService(new MyCodeType())); * CODES.getCodeType(MyCodeType.class); * [...] * SERVICES.getService(TestingCodeService.class).addCodeTypes(new OtherCodeType()); * [..] * TestingUtility.unregisterServices(reg); * </pre> * * @since 3.8.0 */ public class TestingCodeService extends AbstractService implements ICodeService { private static final IScoutLogger LOG = ScoutLogManager.getLogger(TestingCodeService.class); private final Map<Class<? extends ICodeType>, ICodeType<?>> m_codeTypes; private final Object m_codeTypeMapLock; public TestingCodeService(ICodeType<?>... codeTypes) { m_codeTypes = new HashMap<Class<? extends ICodeType>, ICodeType<?>>(); m_codeTypeMapLock = new Object(); addCodeTypes(codeTypes); } public void addCodeTypes(ICodeType<?>... codeTypes) { synchronized (m_codeTypeMapLock) { for (ICodeType<?> ct : codeTypes) { if (ct != null) { m_codeTypes.put(ct.getClass(), ct); } } } } @Override @SuppressWarnings("unchecked") public <T extends ICodeType> T getCodeType(Class<T> type) { synchronized (m_codeTypeMapLock) { return (T) m_codeTypes.get(type); } } @Override public <T extends ICodeType> T getCodeType(Long partitionId, Class<T> type) { synchronized (m_codeTypeMapLock) { return getCodeType(type); } } @Override public ICodeType findCodeTypeById(Object id) { synchronized (m_codeTypeMapLock) { for (ICodeType<?> ct : m_codeTypes.values()) { if (CompareUtility.equals(ct.getId(), id)) { return ct; } } return null; } } @Override public ICodeType findCodeTypeById(Long partitionId, Object id) { synchronized (m_codeTypeMapLock) { return findCodeTypeById(id); } } @Override public ICodeType[] getCodeTypes(Class... types) { synchronized (m_codeTypeMapLock) { List<ICodeType> result = new ArrayList<ICodeType>(); for (Class type : types) { @SuppressWarnings("unchecked") ICodeType ct = getCodeType(type); if (ct != null) { result.add(ct); } } return result.toArray(new ICodeType[result.size()]); } } @Override public ICodeType[] getCodeTypes(Long partitionId, Class... types) { synchronized (m_codeTypeMapLock) { return getCodeTypes(types); } } @Override @SuppressWarnings("unchecked") public <T extends ICode> T getCode(final Class<T> type) { synchronized (m_codeTypeMapLock) { if (type == null) { return null; } Class declaringCodeTypeClass = null; if (type.getDeclaringClass() != null) { // code is inner type of code type or another code Class c = type.getDeclaringClass(); while (c != null && !(ICodeType.class.isAssignableFrom(c))) { c = c.getDeclaringClass(); } declaringCodeTypeClass = c; } if (declaringCodeTypeClass == null) { try { declaringCodeTypeClass = type.newInstance().getCodeType().getClass(); } catch (Throwable t) { LOG.error("find code " + type, t); } } ICodeType codeType = getCodeType(declaringCodeTypeClass); final Holder<ICode> codeHolder = new Holder<ICode>(ICode.class); ICodeVisitor v = new ICodeVisitor() { @Override public boolean visit(ICode code, int treeLevel) { if (code.getClass() == type) { codeHolder.setValue(code); return false; } return true; } }; codeType.visit(v); return (T) codeHolder.getValue(); } } @Override public <T extends ICode> T getCode(Long partitionId, Class<T> type) { synchronized (m_codeTypeMapLock) { return getCode(type); } } @Override public <T extends ICodeType> T reloadCodeType(Class<T> type) { synchronized (m_codeTypeMapLock) { LOG.warn("reloading code types is not supported by this testing ICodeService"); return getCodeType(type); } } @Override public ICodeType[] reloadCodeTypes(Class... types) { synchronized (m_codeTypeMapLock) { LOG.warn("reloading code types is not supported by this testing ICodeService"); return getCodeTypes(types); } } @Override public BundleClassDescriptor[] getAllCodeTypeClasses(String classPrefix) { synchronized (m_codeTypeMapLock) { List<BundleClassDescriptor> result = new ArrayList<BundleClassDescriptor>(); for (Class<? extends ICodeType> type : m_codeTypes.keySet()) { Bundle bundle = FrameworkUtil.getBundle(type); result.add(new BundleClassDescriptor(bundle.getSymbolicName(), type.getName())); } return result.toArray(new BundleClassDescriptor[result.size()]); } } @Override public ICodeType[] getAllCodeTypes(String classPrefix) { synchronized (m_codeTypeMapLock) { List<ICodeType> result = new ArrayList<ICodeType>(); for (ICodeType ct : m_codeTypes.values()) { if (ct.getClass().getName().startsWith(classPrefix)) { result.add(ct); } } return result.toArray(new ICodeType[result.size()]); } } @Override public ICodeType[] getAllCodeTypes(String classPrefix, Long partitionId) { synchronized (m_codeTypeMapLock) { return getAllCodeTypes(classPrefix); } } }
/** * UI model customization wrapping a {@link org.eclipse.core.runtime.Preferences} object with its * location Stored in user area. * * <p>Warning: Only use this class within a ClientJob with an {@link IClientSession}. * * <p>Calling from outside a {@link IClientSession} {@link org.eclipse.scout.rt.client.ClientJob * ClientJob} will produce a warning. In release 3.9 (TODO) will produce an error. */ public class ClientUIPreferences { private static final IScoutLogger LOG = ScoutLogManager.getLogger(ClientUIPreferences.class); /** * @return a new instance of the {@link ClientUIPreferences} based on the {@link * IUserPreferencesStorageService} * <p>Warning: Only use this class within a ClientJob with an {@link IClientSession}. * <p>Calling from outside a {@link IClientSession} {@link * org.eclipse.scout.rt.client.ClientJob ClientJob} will produce a warning. Starting with * release 3.9 it will fail with an error. */ public static ClientUIPreferences getInstance() { return new ClientUIPreferences(ClientSessionThreadLocal.get()); } /** * @return a new instance of the {@link ClientUIPreferences} based on the {@link * IUserPreferencesStorageService} */ public static ClientUIPreferences getInstance(IClientSession session) { return new ClientUIPreferences(session); } private static final String TABLE_CUSTOMIZER_DATA = "table.customizer.data."; private static final String TABLE_COLUMN_UIINDEX = "table.column.viewIndex."; private static final String TABLE_COLUMN_WIDTH = "table.column.width."; private static final String TABLE_COLUMN_VISIBLE = "table.column.visible."; private static final String TABLE_COLUMN_SORT_INDEX = "table.column.sortIndex."; private static final String TABLE_COLUMN_SORT_ASC = "table.column.sortAsc."; private static final String TABLE_COLUMN_SORT_EXPLICIT = "table.column.sortExplicit."; private static final String APPLICATION_WINDOW_MAXIMIZED = "application.window.maximized"; private static final String APPLICATION_WINDOW_BOUNDS = "application.window.bounds"; private static final String CALENDAR_DISPLAY_MODE = "calendar.display.mode"; private static final String CALENDAR_DISPLAY_CONDENSED = "calendar.display.condensed"; private static final String DESKTOP_COLUMN_SPLITS = "desktop.columnSplits"; private static final String FORM_BOUNDS = "form.bounds."; private final IClientSession m_session; private Preferences m_env; private ClientUIPreferences(IClientSession session) { m_session = session; if (m_session == null) { LOG.error( "No scout client session context", new Exception("Calling client preferences from outside a scout client session job")); } load(); } /** * Since this property depends on the user agent it is saved separately for each combination of * {@link org.eclipse.scout.rt.shared.ui.IUiLayer IUiLayer} and {@link * org.eclipse.scout.rt.shared.ui.IUiDeviceType IUiDeviceType}. */ public Rectangle getFormBounds(IForm form) { String key = form.computeCacheBoundsKey(); if (key == null) { return null; } key = getUserAgentPrefix() + FORM_BOUNDS + key; String value = m_env.get(key, ""); if (StringUtility.isNullOrEmpty(value)) { key = getLegacyFormBoundsKey(form); value = m_env.get(key, ""); } if (!StringUtility.isNullOrEmpty(value)) { try { StringTokenizer tok = new StringTokenizer(value, ","); Rectangle r = new Rectangle( new Integer(tok.nextToken()).intValue(), new Integer(tok.nextToken()).intValue(), new Integer(tok.nextToken()).intValue(), new Integer(tok.nextToken()).intValue()); return r; } catch (Exception e) { LOG.warn("value=" + value, e); } } return null; } /** * Since this property depends on the user agent it is saved separately for each combination of * {@link org.eclipse.scout.rt.shared.ui.IUiLayer IUiLayer} and {@link * org.eclipse.scout.rt.shared.ui.IUiDeviceType IUiDeviceType}. */ public void setFormBounds(IForm form, Rectangle bounds) { String key = form.computeCacheBoundsKey(); if (key == null) { return; } key = getUserAgentPrefix() + FORM_BOUNDS + key; if (bounds == null) { m_env.remove(key); } else { m_env.put(key, bounds.x + "," + bounds.y + "," + bounds.width + "," + bounds.height); } flush(); } private String getLegacyFormBoundsKey(IForm form) { String key = form.computeCacheBoundsKey(); if (key == null) { return null; } // Add prefix only if not already added. // This is mainly necessary due to backward compatibility because until 3.8.0 the prefix had to // be returned by computeCacheBoundsKey if (!key.startsWith("form.bounds")) { key = "form.bounds_" + key; } // Explicitly don't consider user agent because before 3.8.0 there was no user agent and // therefore the keys didn't contain this information. return key; } private String getUserAgentPrefix() { UserAgent currentUserAgent = null; if (m_session != null) { currentUserAgent = m_session.getUserAgent(); } else { currentUserAgent = UserAgentUtility.getCurrentUserAgent(); } if (currentUserAgent == null) { return ""; } String uiLayer = null; if (!UiLayer.UNKNOWN.equals(currentUserAgent.getUiLayer())) { uiLayer = currentUserAgent.getUiLayer().getIdentifier(); } String uiDeviceType = null; if (!UiDeviceType.UNKNOWN.equals(currentUserAgent.getUiDeviceType())) { uiDeviceType = currentUserAgent.getUiDeviceType().getIdentifier(); } return StringUtility.concatenateTokens(uiLayer, ".", uiDeviceType, "."); } /** * Since this property depends on the user agent it is saved separately for each combination of * {@link org.eclipse.scout.rt.shared.ui.IUiLayer IUiLayer} and {@link * org.eclipse.scout.rt.shared.ui.IUiDeviceType IUiDeviceType}. * * @since 3.8.0 */ public int[] getSplitterPosition(ISplitBox splitBox) { String baseKey = splitBox.getCacheSplitterPositionPropertyName(); if (baseKey == null) { return null; } String key = getUserAgentPrefix() + baseKey; int[] value = getPropertyIntArray(key); if (value == null) { // If no value has been found try to load with the base key. Done due to backward // compatibility. value = getPropertyIntArray(baseKey); } return value; } /** * Since this property depends on the user agent it is saved separately for each combination of * {@link org.eclipse.scout.rt.shared.ui.IUiLayer IUiLayer} and {@link * org.eclipse.scout.rt.shared.ui.IUiDeviceType IUiDeviceType}. * * @since 3.8.0 */ public void setSplitterPosition(ISplitBox splitBox, int[] weights) { String key = splitBox.getCacheSplitterPositionPropertyName(); if (key == null) { return; } key = getUserAgentPrefix() + key; setPropertyIntArray(key, weights); } public String getTableKey(ITable t) { String key = t.getClass().getName(); String context = t.getUserPreferenceContext(); if (context != null) { key += "#" + context; } return key; } public Object getTableCustomizerData(String customizerKey) { String key = TABLE_CUSTOMIZER_DATA + customizerKey; byte[] serialData = m_env.getByteArray(key, null); if (serialData != null) { try { Object customizerData = SerializationUtility.createObjectSerializer().deserialize(serialData, null); return customizerData; } catch (Throwable t) { LOG.error("Failed reading custom table data for " + key + ": " + t); m_env.remove(key); return null; } } else { return null; } } /** store customizer data to persistent store */ public void setTableCustomizerData(String customizerKey, Object customizerData) { String key = TABLE_CUSTOMIZER_DATA + customizerKey; if (customizerData != null) { try { byte[] data = SerializationUtility.createObjectSerializer().serialize(customizerData); m_env.putByteArray(key, data); } catch (Throwable t) { LOG.error("Failed storing custom table data for " + key, t); m_env.remove(key); } } else { m_env.remove(key); } // flush(); } /** @return the key prefix used to store column data */ public String getColumnKey(IColumn c) { String key = c.getColumnId(); if (c.getTable() != null) { key = getTableKey(c.getTable()) + "#" + key; } return key; } public void setTableColumnPreferences(IColumn col) { setTableColumnPreferences(col, true); } public void setTableColumnPreferences(IColumn col, boolean flush) { String keySuffix = getColumnKey(col); String key = TABLE_COLUMN_UIINDEX + keySuffix; int viewIndex = col.getVisibleColumnIndexHint(); boolean visible = col.isVisibleInternal(); int width = col.getWidth(); int sortIndex = col.getSortIndex(); boolean sortUp = col.isSortAscending(); boolean sortExplicit = col.isSortExplicit(); // if (viewIndex >= 0) { m_env.put(key, "" + viewIndex); } else { m_env.remove(key); } // key = TABLE_COLUMN_VISIBLE + keySuffix; if (!visible) { m_env.put(key, "no"); } else { m_env.put(key, "yes"); } // key = getUserAgentPrefix() + TABLE_COLUMN_WIDTH + keySuffix; if (width >= 0) { m_env.put(key, "" + width); } else { m_env.remove(key); } // key = TABLE_COLUMN_SORT_INDEX + keySuffix; if (sortIndex >= 0) { m_env.put(key, "" + sortIndex); } else { m_env.put(key, "-1"); } // key = TABLE_COLUMN_SORT_ASC + keySuffix; if (sortIndex >= 0 && sortUp) { m_env.put(key, "true"); } else { m_env.put(key, "false"); } // key = TABLE_COLUMN_SORT_EXPLICIT + keySuffix; if (sortExplicit) { m_env.put(key, "true"); } else { m_env.put(key, "false"); } if (flush) { flush(); } } public void updateTableColumnOrder(List<IColumn<?>> columnList, int[] visibleColumnIndexHints) { if (columnList.size() != visibleColumnIndexHints.length) { throw new IllegalArgumentException( "columnList.size=" + columnList.size() + " hints.length=" + visibleColumnIndexHints.length); } for (int i = 0; i < visibleColumnIndexHints.length; i++) { IColumn<?> c = columnList.get(i); int viewIndex = visibleColumnIndexHints[i]; String keySuffix = getColumnKey(c); String key = TABLE_COLUMN_UIINDEX + keySuffix; if (viewIndex >= 0) { m_env.put(key, "" + viewIndex); } else { m_env.remove(key); } } // flush(); } public void removeTableColumnPreferences(IColumn col) { removeTableColumnPreferences(col, true, true, true, true); } public void removeTableColumnPreferences( IColumn col, boolean visibility, boolean order, boolean sorting, boolean widths) { removeTableColumnPreferences(col, visibility, order, sorting, widths, true); } private void removeTableColumnPreferences( IColumn col, boolean visibility, boolean order, boolean sorting, boolean widths, boolean flush) { if (col != null) { String keySuffix = getColumnKey(col); if (visibility) { m_env.remove(TABLE_COLUMN_VISIBLE + keySuffix); } if (order) { m_env.remove(TABLE_COLUMN_UIINDEX + keySuffix); } if (sorting) { m_env.remove(TABLE_COLUMN_SORT_INDEX + keySuffix); m_env.remove(TABLE_COLUMN_SORT_ASC + keySuffix); m_env.remove(TABLE_COLUMN_SORT_EXPLICIT + keySuffix); } if (widths) { m_env.remove(getUserAgentPrefix() + TABLE_COLUMN_WIDTH + keySuffix); } if (flush) { flush(); } } } public void removeAllTableColumnPreferences( ITable table, boolean visibility, boolean order, boolean sorting, boolean widths) { if (table == null) { return; } for (IColumn<?> col : table.getColumns()) { removeTableColumnPreferences(col, visibility, order, sorting, widths, false); } flush(); } public void setAllTableColumnPreferences(ITable table) { if (table == null) { return; } for (IColumn col : table.getColumns()) { if (col.isDisplayable()) { setTableColumnPreferences(col, false); } } flush(); } /** @return true if there are any user preferences for this tables columns */ public boolean hasTableColumnPreferences(ITable table) { if (table != null) { for (IColumn col : table.getColumns()) { String keySuffix = getColumnKey(col); if (m_env.get(TABLE_COLUMN_VISIBLE + keySuffix, null) != null) { return true; } if (m_env.get(TABLE_COLUMN_UIINDEX + keySuffix, null) != null) { return true; } if (m_env.get(TABLE_COLUMN_SORT_INDEX + keySuffix, null) != null) { return true; } if (m_env.get(TABLE_COLUMN_SORT_ASC + keySuffix, null) != null) { return true; } if (m_env.get(TABLE_COLUMN_SORT_EXPLICIT + keySuffix, null) != null) { return true; } if (m_env.get(TABLE_COLUMN_WIDTH + keySuffix, null) != null) { return true; } } } return false; } /** * Since this property depends on the user agent it is saved separately for each combination of * {@link org.eclipse.scout.rt.shared.ui.IUiLayer IUiLayer} and {@link * org.eclipse.scout.rt.shared.ui.IUiDeviceType IUiDeviceType}. */ public int getTableColumnWidth(IColumn col, int defaultWidth) { String keySuffix = getColumnKey(col); String baseKey = TABLE_COLUMN_WIDTH + keySuffix; String key = getUserAgentPrefix() + baseKey; String value = m_env.get(key, null); if (value == null) { // If no value has been found try to load with the base key. Done due to backward // compatibility. value = m_env.get(baseKey, null); } if (value != null) { try { return Integer.parseInt(value); } catch (Exception e) { LOG.warn("value=" + value, e); } } return defaultWidth; } public boolean getTableColumnVisible(IColumn col, boolean defaultValue) { String keySuffix = getColumnKey(col); String key = TABLE_COLUMN_VISIBLE + keySuffix; String value = m_env.get(key, null); if (value != null) { Boolean b = TypeCastUtility.castValue(value, Boolean.class); return b != null ? b.booleanValue() : defaultValue; } return defaultValue; } public int getTableColumnViewIndex(IColumn col, int defaultIndex) { String keySuffix = getColumnKey(col); String key = TABLE_COLUMN_UIINDEX + keySuffix; String value = m_env.get(key, null); if (value != null) { try { return Integer.parseInt(value); } catch (Exception e) { LOG.warn("value=" + value, e); } } return defaultIndex; } public int getTableColumnSortIndex(IColumn col, int defaultValue) { String keySuffix = getColumnKey(col); String key = TABLE_COLUMN_SORT_INDEX + keySuffix; String value = m_env.get(key, null); if (value != null) { Integer i = TypeCastUtility.castValue(value, Integer.class); return i.intValue(); } return defaultValue; } public boolean getTableColumnSortAscending(IColumn col, boolean defaultValue) { String keySuffix = getColumnKey(col); String key = TABLE_COLUMN_SORT_ASC + keySuffix; String value = m_env.get(key, null); if (value != null) { Boolean b = TypeCastUtility.castValue(value, Boolean.class); return b != null ? b.booleanValue() : defaultValue; } return defaultValue; } public Boolean getTableColumnSortExplicit(IColumn col) { String keySuffix = getColumnKey(col); String key = TABLE_COLUMN_SORT_EXPLICIT + keySuffix; String value = m_env.get(key, null); if (value != null) { return TypeCastUtility.castValue(value, Boolean.class); } return null; } public void setApplicationWindowPreferences(BoundsSpec r, boolean maximized) { if (r != null) { String value = "" + r.x + "," + r.y + "," + r.width + "," + r.height; m_env.put(APPLICATION_WINDOW_BOUNDS, value); } else { m_env.remove(APPLICATION_WINDOW_BOUNDS); } // if (maximized) { m_env.put(APPLICATION_WINDOW_MAXIMIZED, "yes"); } else { m_env.remove(APPLICATION_WINDOW_MAXIMIZED); } flush(); } public boolean getApplicationWindowMaximized() { String key = APPLICATION_WINDOW_MAXIMIZED; String value = m_env.get(key, null); return "yes".equalsIgnoreCase(value); } public BoundsSpec getApplicationWindowBounds() { String key = APPLICATION_WINDOW_BOUNDS; String value = m_env.get(key, null); if (value != null) { try { StringTokenizer tok = new StringTokenizer(value, ","); BoundsSpec r = new BoundsSpec( new Integer(tok.nextToken()).intValue(), new Integer(tok.nextToken()).intValue(), new Integer(tok.nextToken()).intValue(), new Integer(tok.nextToken()).intValue()); return r; } catch (Exception e) { LOG.warn("value=" + value, e); } } return null; } public void setCalendarPreferences(int displayMode, boolean displayCondensed) { m_env.put(CALENDAR_DISPLAY_MODE, "" + displayMode); m_env.put(CALENDAR_DISPLAY_CONDENSED, "" + displayCondensed); flush(); } public int getCalendarDisplayMode(int defaultValue) { String key = CALENDAR_DISPLAY_MODE; String value = m_env.get(key, null); if (value != null) { try { return Integer.parseInt(value); } catch (Exception e) { LOG.warn("value=" + value, e); } } return defaultValue; } public boolean getCalendarDisplayCondensed(boolean defaultValue) { String key = CALENDAR_DISPLAY_CONDENSED; String value = m_env.get(key, null); if (value != null) { try { return TypeCastUtility.castValue(value, Boolean.class); } catch (Exception e) { LOG.warn("value=" + value, e); } } return defaultValue; } public int getPropertyInteger(String propName, int defaultValue, boolean setDefaultAsProperty) { String value = m_env.get(propName, null); if (value != null) { try { return TypeCastUtility.castValue(value, Integer.class); } catch (Exception e) { LOG.warn("value=" + value, e); if (setDefaultAsProperty) { setPropertyInteger(propName, defaultValue); } } } else { if (setDefaultAsProperty) { setPropertyInteger(propName, defaultValue); } } return defaultValue; } public void setPropertyInteger(String propName, int value) { m_env.put(propName, "" + value); flush(); } public int[] getPropertyIntArray(String propName) { String strVal = m_env.get(propName, null); if (!StringUtility.hasText(strVal)) { return null; } String[] split = strVal.split(";"); int[] val = new int[split.length]; for (int i = 0; i < split.length; i++) { val[i] = Integer.parseInt(split[i]); } return val; } public void setPropertyIntArray(String propName, int[] value) { StringBuilder builder = new StringBuilder(); if (value != null) { for (int i = 0; i < value.length; i++) { builder.append(value[i]); if (i != value.length - 1) { builder.append(";"); } } } m_env.put(propName, builder.toString()); flush(); } public Double getPropertyDouble(String propName) { String value = m_env.get(propName, null); if (value != null) { try { return TypeCastUtility.castValue(value, Double.class); } catch (Exception e) { LOG.warn("value=" + value, e); } } return null; } public void setPropertyDouble(String propName, Double value) { m_env.put(propName, "" + value); flush(); } public int[][] getDesktopColumnSplits(int rowCount, int colCount) { // the row x col matrix is stored as flat int array, row per row, column per column int[] a = getPropertyIntArray(DESKTOP_COLUMN_SPLITS); if (a != null && a.length == rowCount * colCount) { int[][] splits = new int[rowCount][colCount]; int index = 0; for (int r = 0; r < rowCount; r++) { for (int c = 0; c < colCount; c++) { splits[r][c] = a[index]; index++; } } return splits; } return null; } public void setDesktopColumnSplits(int[][] splits) { // the row x col matrix is stored as flat int array, row per row, column per column if (splits != null) { int rowCount = splits.length; int colCount = splits[0].length; int[] a = new int[rowCount * colCount]; int index = 0; for (int r = 0; r < rowCount; r++) { for (int c = 0; c < colCount; c++) { a[index] = splits[r][c]; index++; } } setPropertyIntArray(DESKTOP_COLUMN_SPLITS, a); } } protected void load() { if (m_session == null || ClientSessionThreadLocal.get() == m_session) { m_env = SERVICES.getService(IUserPreferencesStorageService.class).loadPreferences(); } else { ClientAsyncJob job = new ClientAsyncJob("Load user preferences", m_session) { @Override protected void runVoid(IProgressMonitor monitor) throws Throwable { m_env = SERVICES.getService(IUserPreferencesStorageService.class).loadPreferences(); } }; job.schedule(); try { job.join(); } catch (InterruptedException e) { // nop } } if (m_env == null) { throw new IllegalStateException("Could not load preferences in client job"); } } protected void flush() { try { m_env.flush(); } catch (Throwable t) { t.printStackTrace(); } } }
public abstract class AbstractRwtScoutSvgComposite<T extends IFormField> extends RwtScoutFieldComposite<T> { private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractRwtScoutSvgComposite.class); /* because the scroll-bar layout of IE is different: add an offset to ensure the full svg element can be shown without scrollbars */ protected static final int SVG_ELEMENT_INNER_SPACE = 7; private static final String DOCUMENT_ENCODING = "UTF-8"; private BrowserExtension m_browserExtension; private void setBrowserExtension(BrowserExtension browserExtension) { m_browserExtension = browserExtension; } protected BrowserExtension getBrowserExtension() { return m_browserExtension; } @Override protected void initializeUi(Composite parent) { super.initializeUi(parent); // create container for label and svg browser Composite container = getUiEnvironment().getFormToolkit().createComposite(parent); setUiContainer(container); // create label StatusLabelEx label = getUiEnvironment().getFormToolkit().createStatusLabel(container, getScoutObject()); // create browser that shows the SVG Browser browser = getUiEnvironment().getFormToolkit().createBrowser(container, SWT.NO_SCROLL); browser.addDisposeListener( new DisposeListener() { private static final long serialVersionUID = 1L; @Override public void widgetDisposed(DisposeEvent e) { getBrowserExtension().detach(); } }); browser.addLocationListener( new LocationAdapter() { private static final long serialVersionUID = 1L; @Override public void changed(LocationEvent event) { locationChangedFromUi(event); } }); browser.addControlListener( new ControlListener() { private static final long serialVersionUID = 1L; @Override public void controlResized(ControlEvent e) { updateSvgDocument(); } @Override public void controlMoved(ControlEvent e) { updateSvgDocument(); } }); setBrowserExtension(new BrowserExtension(browser)); getBrowserExtension().attach(); setUiLabel(label); setUiField(browser); // layout getUiContainer().setLayout(new LogicalGridLayout(1, 0)); } protected static String getSvgContentFromDocument(SVGDocument doc) throws ProcessingException { try { ByteArrayOutputStream out = new ByteArrayOutputStream(); DOMSource domSource = new DOMSource(doc.getRootElement()); StreamResult streamResult = new StreamResult(out); Transformer t = TransformerFactory.newInstance().newTransformer(); t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); t.setOutputProperty(OutputKeys.ENCODING, DOCUMENT_ENCODING); t.transform(domSource, streamResult); out.close(); return new String(out.toByteArray(), DOCUMENT_ENCODING); } catch (Exception e) { throw new ProcessingException("Writing SVG Failed", e); } } protected void updateSvgDocument() { getBrowserExtension().clearLocalHyperlinkCache(); getBrowserExtension().clearResourceCache(); SVGDocument doc = getSvgDocument(); if (doc == null) { getUiField().setText(""); return; } try { // set the dimensions of the svg element to the size of the browser field Rectangle browserBounds = getAbsoluteBrowserBounds(); doc.getRootElement() .setAttribute(SVGConstants.SVG_HEIGHT_ATTRIBUTE, browserBounds.height + "px"); doc.getRootElement() .setAttribute(SVGConstants.SVG_WIDTH_ATTRIBUTE, browserBounds.width + "px"); // get the svg code as string and rewrite the local links String svgText = getBrowserExtension().adaptLocalHyperlinks(getSvgContentFromDocument(doc), 2); // bugfix for SVG fields to ensure all context menus are closed when the user clicks into the // svg field String contextMenuHideScript = "parent.parent.org.eclipse.rwt.MenuManager.getInstance().update(null, 'mousedown');"; // bugfix so that the svg field inherits the color of the parent container. otherwise it is // always defined white. String backgroundColorInheritScript = null; if (getScoutObject().getBackgroundColor() == null) { backgroundColorInheritScript = "var iframes = parent.document.getElementsByTagName('iframe');" + "for(var i=0;i<iframes.length;i++) {" + " var field=iframes[i].parentNode;" + " var color=field.style.backgroundColor;" + " if(color && color.toLowerCase() === 'rgb(255, 255, 255)') " + " field.style.backgroundColor='';" + "}"; } else { backgroundColorInheritScript = ""; } // set the html content to the browser getUiField() .setText( "<html><body width=\"100%\" height=\"100%\" onload=\"" + backgroundColorInheritScript + "\" onclick=\"" + contextMenuHideScript + "\">" + svgText + "</body></html>"); } catch (Exception e) { LOG.error("preparing svg browser content", e); getUiField().setText(""); } } protected Rectangle getAbsoluteBrowserBounds() { Point pt = getUiField().getDisplay().map(getUiField(), null, new Point(0, 0)); return new Rectangle( pt.x, pt.y, getUiField().getBounds().width - SVG_ELEMENT_INNER_SPACE, getUiField().getBounds().height); } @Override public Browser getUiField() { return (Browser) super.getUiField(); } protected abstract SVGDocument getSvgDocument(); protected abstract void locationChangedFromUi(LocationEvent event); @Override protected void setEnabledFromScout(boolean b) { // nop } }
/** * This resolver intercepts webservice requests prior to being propagated to the port type in order * to bind the call to a {@link IServerSession} context. */ @SuppressWarnings("restriction") public class ScoutInstanceResolver<T> extends AbstractMultiInstanceResolver<T> { private static final IScoutLogger LOG = ScoutLogManager.getLogger(ScoutInstanceResolver.class); private IServerSessionFactory m_sessionFactory; public ScoutInstanceResolver(Class<T> portTypeClass) { super(portTypeClass); if (portTypeClass == null) { throw new WebServiceException("No port type class configured in sun-jaxws.xml"); } } @Override public void start(WSWebServiceContext context, WSEndpoint endpoint) { m_sessionFactory = createSessionFactory(clazz); super.start(context, endpoint); } @Override public T resolve(Packet packet) { return super .create(); // creates a new port type instance, injects the @{WebServiceContext} and invokes // the method annotated with @{link PostConstruct} } protected IServerSessionFactory createSessionFactory(Class<?> portTypeClass) { ScoutWebService annotation = portTypeClass.getAnnotation(ScoutWebService.class); if (annotation == null) { return null; } try { return annotation.sessionFactory().newInstance(); } catch (Exception e) { LOG.error("Error occured while creating session factory.", e); } return null; } protected IServerSession getSession(MessageContext context) { if (m_sessionFactory == null) { return null; } // Prefer cached session over creating a new one. // However, the session is only considered if created by the same type of factory. // This is to ensure a proper session context which is what the user is expecting. IServerSession contextSession = ContextHelper.getContextSession(context); Class<? extends IServerSessionFactory> contextSessionFactory = ContextHelper.getContextSessionFactoryClass(context); if (contextSession == null || !CompareUtility.equals(m_sessionFactory.getClass(), contextSessionFactory)) { // create a new session return SessionHelper.createNewServerSession(m_sessionFactory); } // cached session return contextSession; } @Override public Invoker createInvoker() { return new P_Invoker(); } protected class P_Invoker extends Invoker { protected WSWebServiceContext m_context; @Override public void start(final WSWebServiceContext context, final WSEndpoint endpoint) { m_context = context; ScoutInstanceResolver.this.start(context, endpoint); } @Override public void dispose() { m_context = null; ScoutInstanceResolver.this.dispose(); } @Override public Object invoke(final Packet packet, final Method method, final Object... aobj) throws InvocationTargetException, IllegalAccessException { final T portType = ScoutInstanceResolver.this.resolve(packet); if (portType == null) { throw new WebServiceException("No port type found"); } Subject subject = null; try { subject = Subject.getSubject(AccessController.getContext()); } catch (Exception e) { LOG.error("Failed to get subject of calling access context", e); } if (subject == null) { throw new WebServiceException( "Webservice request was NOT dispatched due to security reasons: request must run on behalf of a subject context."); } IServerSession session = getSession(m_context.getMessageContext()); if (session == null) { LOG.warn( "Webservice request is not run in a session context as no server session is configured."); return method.invoke(portType, aobj); } try { final ObjectHolder resultHolder = new ObjectHolder(); final Holder<InvocationTargetException> invocationTargetExceptionHolder = new Holder<InvocationTargetException>(InvocationTargetException.class); final Holder<IllegalAccessException> illegalAccessExceptionHolder = new Holder<IllegalAccessException>(IllegalAccessException.class); final Holder<RuntimeException> runtimeExceptionHolder = new Holder<RuntimeException>(RuntimeException.class); // run server job final IServerJobFactory jobFactory = SERVICES.getService(IServerJobService.class).createJobFactory(session, subject); ServerJob serverJob = jobFactory.create( "Tx", new ITransactionRunnable() { @Override public IStatus run(IProgressMonitor monitor) throws ProcessingException { try { resultHolder.setValue(method.invoke(portType, aobj)); } catch (InvocationTargetException e) { Throwable cause = e.getCause(); ThreadContext.getTransaction().addFailure(cause); // rollback transaction if (cause instanceof RuntimeException) { LOG.warn( "Webservice processing exception occured. Please handle faults by respective checked SOAP faults.", cause); invocationTargetExceptionHolder.setValue( new InvocationTargetException( new WebServiceException("Internal Server Error"))); } else { // business exception (SOAP faults are checked exceptions) LOG.info("Webservice processing exception occured.", cause); invocationTargetExceptionHolder.setValue(e); } } catch (IllegalAccessException e) { ThreadContext.getTransaction().addFailure(e); // rollback transaction LOG.error( "Illegal access exception occured while dispatching webservice request. This might be caused because of Java security settings.", e); illegalAccessExceptionHolder.setValue(e); } catch (RuntimeException e) { ThreadContext.getTransaction().addFailure(e); // rollback transaction LOG.error( "Unexpected error occured while dispatching webservice request.", e); runtimeExceptionHolder.setValue(e); } return Status.OK_STATUS; } }); serverJob.setSystem(true); serverJob.runNow(new NullProgressMonitor()); if (invocationTargetExceptionHolder.getValue() != null) { throw invocationTargetExceptionHolder.getValue(); } if (illegalAccessExceptionHolder.getValue() != null) { throw illegalAccessExceptionHolder.getValue(); } if (runtimeExceptionHolder.getValue() != null) { throw runtimeExceptionHolder.getValue(); } return resultHolder.getValue(); } finally { postInvoke(packet, portType); } } } }
public abstract class AbstractKeyboardNavigationSupport { private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractKeyboardNavigationSupport.class); private final long m_delay; private long m_timeoutTimestamp; private String m_filterText = ""; private Object navigationLock = new Object(); private P_NavigationJob m_navigationJob; public AbstractKeyboardNavigationSupport() { this(1000L); } public AbstractKeyboardNavigationSupport(long delay) { m_delay = delay; m_navigationJob = new P_NavigationJob(); } public void addChar(char c) { synchronized (navigationLock) { if (Character.isWhitespace(c) || Character.isLetterOrDigit(c)) { if (System.currentTimeMillis() > m_timeoutTimestamp) { m_filterText = ""; } String newText = "" + Character.toLowerCase(c); m_filterText += newText; if (m_navigationJob != null) { m_navigationJob.cancel(); } else { m_navigationJob = new P_NavigationJob(); } m_navigationJob.schedule(250L); m_timeoutTimestamp = System.currentTimeMillis() + m_delay; } } } abstract void handleSearchPattern(String regex); private class P_NavigationJob extends Job { public P_NavigationJob() { super(""); setSystem(true); } @Override protected IStatus run(IProgressMonitor monitor) { String pattern; synchronized (navigationLock) { if (monitor.isCanceled() || StringUtility.isNullOrEmpty(m_filterText)) { return Status.CANCEL_STATUS; } pattern = StringUtility.toRegExPattern(m_filterText.toLowerCase()); pattern = pattern + ".*"; } // this call must be outside lock! handleSearchPattern(pattern); return Status.OK_STATUS; } } // end class P_NavigationJob }
@ClassId("6a093505-c2b1-4df2-84d6-e799f91e6e7c") public abstract class AbstractGroupBox extends AbstractCompositeField implements IGroupBox { private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractGroupBox.class); private IGroupBoxUIFacade m_uiFacade; private boolean m_mainBoxFlag = false; private int m_gridColumnCountHint; private boolean m_scrollable; private List<IFormField> m_controlFields; private List<IGroupBox> m_groupBoxes; private List<IButton> m_customButtons; private List<IButton> m_systemButtons; private IGroupBoxBodyGrid m_bodyGrid; private GroupBoxProcessButtonGrid m_customProcessButtonGrid; private GroupBoxProcessButtonGrid m_systemProcessButtonGrid; public AbstractGroupBox() { this(true); } public AbstractGroupBox(boolean callInitializer) { super(callInitializer); } /** {@inheritDoc} Default for group boxes is true. */ @Override protected boolean getConfiguredGridUseUiHeight() { return true; } /** * Configures the number of columns used in this group box.<br> * A typical {@link IFormField} inside a group box spans one column. This behavior can be changed * by setting {@link AbstractFormField#getConfiguredGridW()}. * * <p>Subclasses can override this method. Default is -1 which typically means 2 columns. * * @return the number of columns used in this group box */ @ConfigProperty(ConfigProperty.INTEGER) @Order(200) protected int getConfiguredGridColumnCount() { return -1; } /** @return the body grid responsible to set {@link GridData} to the fields in this group box. */ @ConfigProperty(ConfigProperty.GROUP_BOX_BODY_GRID) @Order(210) protected Class<? extends IGroupBoxBodyGrid> getConfiguredBodyGrid() { return VerticalSmartGroupBoxBodyGrid.class; } /** * Configures the border visibility for this group box. <br> * If the property is set to true, a border will be displayed around the group box. The style of * the border is configured by {@link #getConfiguredBorderDecoration()}.<br> * If the property is set to false, no border will be displayed and the margin reserved for the * border will be removed. * * <p><b>Hint:</b> Keep in mind that setting the border to invisible also removes the margin which * could lead to a misalignment of the fields if several group boxes are used on a form. In order * to preserve the correct alignment consider using {@link #getConfiguredBorderDecoration()} with * {@link IGroupBox#BORDER_DECORATION_EMPTY} and {@link #getConfiguredBorderVisible()} with {@code * true} instead. * * <p>Subclasses can override this method. Default is {@code true}. * * @return {@code true} if the border is visible, {@code false} otherwise. */ @ConfigProperty(ConfigProperty.BOOLEAN) @Order(230) protected boolean getConfiguredBorderVisible() { return true; } /** * Configures whether this group box should be expandable or not.<br> * This property depends on the border decoration which can be configured by {@link * #getConfiguredBorderDecoration()}. It typically only has an effect if the border decoration is * set to {@link IGroupBox#BORDER_DECORATION_SECTION} or {@link IGroupBox#BORDER_DECORATION_AUTO}. * * <p>Subclasses can override this method. Default is {@code false}. * * @return {@code true} if the group box should be expandable, {@code false} otherwise. */ @ConfigProperty(ConfigProperty.BOOLEAN) @Order(231) protected boolean getConfiguredExpandable() { return false; } /** * Configures whether this group box is initially expanded. <br> * This property only has an effect if the group box is expandable which can be configured by * {@link #getConfiguredExpandable()}. * * <p>Subclasses can override this method. Default is {@code true}. * * @return {@code true} if the group box should be initially expanded, {@code false} otherwise. */ @ConfigProperty(ConfigProperty.BOOLEAN) @Order(232) protected boolean getConfiguredExpanded() { return true; } /** * Configures the border decoration for this group box. See {@code IGroupBox#BORDER_DECORATION_*} * constants for valid values.<br> * This property only has an effect if the border is visible which can be configured by {@link * #getConfiguredBorderVisible()}. * * <p>Subclasses can override this method. Default is {@link IGroupBox#BORDER_DECORATION_AUTO}. * * @return the border decoration of the group box */ @ConfigProperty(ConfigProperty.BORDER_DECORATION) @Order(233) protected String getConfiguredBorderDecoration() { return BORDER_DECORATION_AUTO; } /** * Configures the background image for this group box. * * <p>Subclasses can override this method. Default is {@code null}. * * @return the ID (name) of the image * @see IIconProviderService */ @ConfigProperty(ConfigProperty.ICON_ID) @Order(240) protected String getConfiguredBackgroundImageName() { return null; } /** * Configures the horizontal alignment of the background image.<br> * This property only has an effect if the group box has a background image which can be * configured by {@link #getConfiguredBackgroundImageName()} * * <p>Subclasses can override this method. Default alignment is center. * * @return -1 for left, 0 for center and 1 for right alignment */ @ConfigProperty(ConfigProperty.HORIZONTAL_ALIGNMENT) @Order(250) protected int getConfiguredBackgroundImageHorizontalAlignment() { return 0; } /** * Configures the vertical alignment of the background image.<br> * This property only has an effect if the group box has a background image which can be * configured by {@link #getConfiguredBackgroundImageName()} * * <p>Subclasses can override this method. Default alignment is center. * * @return -1 for top, 0 for center and 1 for bottom alignment */ @ConfigProperty(ConfigProperty.VERTICAL_ALIGNMENT) @Order(260) protected int getConfiguredBackgroundImageVerticalAlignment() { return 0; } /** * Configures whether this group box should be scrollable.</br> If the property is set to true, a * vertical scrollbar will appear if the content is too large to be displayed. * * <p>Subclasses can override this method. Default is false. * * @return {@code true} if the group box should be scrollable, {@code false} otherwise. */ @ConfigProperty(ConfigProperty.BOOLEAN) @Order(270) protected boolean getConfiguredScrollable() { return false; } /** * Configures the column span of this group box.<br> * The value defined by this property refers to the number of columns defined by the container of * this group box. <br> * The column count of the container, which actually is the parent group box, can be configured by * {@link #getConfiguredGridColumnCount()} (you need to configure that in the parent group box). * * <p><b>Example:</b> If the column count of the container is set to 3 and a column span of this * group box is set to 2 it means 2/3 of the container width is used for this group box. * * <p>Subclasses can override this method. Default is {@link IFormField#FULL_WIDTH} which means it * spans every column of the container. * * @return the number of columns to span */ @Override protected int getConfiguredGridW() { return FULL_WIDTH; } @Override protected void initConfig() { m_uiFacade = new P_UIFacade(); Class<? extends IGroupBoxBodyGrid> bodyGridClazz = getConfiguredBodyGrid(); if (bodyGridClazz != null) { IGroupBoxBodyGrid bodyGrid; try { bodyGrid = bodyGridClazz.newInstance(); setBodyGrid(bodyGrid); } catch (Exception e) { SERVICES .getService(IExceptionHandlerService.class) .handleException( new ProcessingException( "error creating instance of class '" + bodyGridClazz.getName() + "'.", e)); } } m_customProcessButtonGrid = new GroupBoxProcessButtonGrid(this, true, false); m_systemProcessButtonGrid = new GroupBoxProcessButtonGrid(this, false, true); super.initConfig(); categorizeFields(); setExpandable(getConfiguredExpandable()); setExpanded(getConfiguredExpanded()); setBorderVisible(getConfiguredBorderVisible()); setBorderDecoration(getConfiguredBorderDecoration()); setGridColumnCountHint(getConfiguredGridColumnCount()); setBackgroundImageName(getConfiguredBackgroundImageName()); setBackgroundImageHorizontalAlignment(getConfiguredBackgroundImageHorizontalAlignment()); setBackgroundImageVerticalAlignment(getConfiguredBackgroundImageVerticalAlignment()); setScrollable(getConfiguredScrollable()); } private void categorizeFields() { // categorize items List<IFormField> controlList = new ArrayList<IFormField>(); List<IGroupBox> groupList = new ArrayList<IGroupBox>(); List<IButton> customButtonList = new ArrayList<IButton>(); List<IButton> systemButtonList = new ArrayList<IButton>(); for (IFormField field : getFields()) { if (field instanceof IGroupBox) { groupList.add((IGroupBox) field); controlList.add(field); } else if (field instanceof IButton) { IButton b = (IButton) field; if (b.isProcessButton()) { if (b.getSystemType() != IButton.SYSTEM_TYPE_NONE) { systemButtonList.add((IButton) field); } else { customButtonList.add((IButton) field); } } else { controlList.add(field); } } else { controlList.add(field); } } m_controlFields = controlList; m_groupBoxes = groupList; m_customButtons = customButtonList; m_systemButtons = systemButtonList; } private void ensureCategorized() { if (m_controlFields == null || m_groupBoxes == null || m_customButtons == null || m_systemButtons == null) { categorizeFields(); } } private void clearCategorization() { m_controlFields = null; m_groupBoxes = null; m_customButtons = null; m_systemButtons = null; } @Override public List<IKeyStroke> getContributedKeyStrokes() { List<IKeyStroke> list = new ArrayList<IKeyStroke>(2); if (isMainBox() && (getForm() != null && getForm().getOuterForm() == null)) { // add default escape and enter key stroke only if no similar key stroke // is defined on the mainbox boolean hasEnter = false; boolean hasEscape = false; for (IKeyStroke ks : getLocalKeyStrokes()) { if ("enter".equalsIgnoreCase(ks.getKeyStroke())) { hasEnter = true; } if ("escape".equalsIgnoreCase(ks.getKeyStroke())) { hasEscape = true; } } if (!hasEnter) { try { DefaultFormEnterKeyStroke enterKeyStroke = new DefaultFormEnterKeyStroke(getForm()); enterKeyStroke.initAction(); list.add(enterKeyStroke); } catch (ProcessingException e) { LOG.error("could not initialize enter key stroke.", e); } } if (!hasEscape) { try { DefaultFormEscapeKeyStroke escKeyStroke = new DefaultFormEscapeKeyStroke(getForm()); escKeyStroke.initAction(); list.add(escKeyStroke); } catch (ProcessingException e) { LOG.error("could not initialize esc key stroke.", e); } } } return list; } @Override public void rebuildFieldGrid() { m_bodyGrid.validate(this); m_customProcessButtonGrid.validate(); m_systemProcessButtonGrid.validate(); if (isInitialized()) { if (getForm() != null) { getForm().structureChanged(this); } } } @Override public boolean isMainBox() { return m_mainBoxFlag; } @Override public void setMainBox(boolean b) { m_mainBoxFlag = b; } @Override public int getGroupBoxIndex(IGroupBox groupBox) { return m_groupBoxes.indexOf(groupBox); } @Override public int getCustomProcessButtonCount() { return m_customButtons.size(); } @Override public int getGroupBoxCount() { return m_groupBoxes.size(); } @Override public int getSystemProcessButtonCount() { return m_systemButtons.size(); } @Override public List<IGroupBox> getGroupBoxes() { ensureCategorized(); return CollectionUtility.arrayList(m_groupBoxes); } @Override public List<IFormField> getControlFields() { ensureCategorized(); return CollectionUtility.arrayList(m_controlFields); } @Override public List<IButton> getCustomProcessButtons() { ensureCategorized(); return CollectionUtility.arrayList(m_customButtons); } @Override public List<IButton> getSystemProcessButtons() { ensureCategorized(); return CollectionUtility.arrayList(m_systemButtons); } public void setBodyGrid(IGroupBoxBodyGrid bodyGrid) { m_bodyGrid = bodyGrid; } @Override public void addField(IFormField f) { super.addField(f); clearCategorization(); } @Override public void removeField(IFormField f) { super.removeField(f); clearCategorization(); } @Override public IGroupBoxBodyGrid getBodyGrid() { return m_bodyGrid; } @Override public final int getGridColumnCount() { return m_bodyGrid.getGridColumnCount(); } @Override public final int getGridRowCount() { return m_bodyGrid.getGridRowCount(); } @Override public void setGridColumnCountHint(int c) { m_gridColumnCountHint = c; if (isInitialized()) { rebuildFieldGrid(); } } @Override public int getGridColumnCountHint() { return m_gridColumnCountHint; } @Override public boolean isScrollable() { return m_scrollable; } @Override public void setScrollable(boolean scrollable) { if (m_scrollable != scrollable) { m_scrollable = scrollable; if (m_scrollable) { // force weighty to be > 0 GridData gd = getGridDataHints(); if (gd.weightY <= 0) { gd.weightY = 1; setGridDataHints(gd); } } } } // box is only visible when it has at least one visible item @Override protected void handleFieldVisibilityChanged() { super.handleFieldVisibilityChanged(); if (isInitialized()) { rebuildFieldGrid(); } } @Override public boolean isBorderVisible() { return propertySupport.getPropertyBool(PROP_BORDER_VISIBLE); } @Override public void setBorderVisible(boolean b) { propertySupport.setPropertyBool(PROP_BORDER_VISIBLE, b); } @Override public String getBorderDecoration() { return propertySupport.getPropertyString(PROP_BORDER_DECORATION); } @Override public void setBorderDecoration(String s) { propertySupport.setPropertyString(PROP_BORDER_DECORATION, s); } @Override public boolean isExpandable() { return propertySupport.getPropertyBool(PROP_EXPANDABLE); } @Override public void setExpandable(boolean b) { propertySupport.setPropertyBool(PROP_EXPANDABLE, b); } @Override public boolean isExpanded() { return propertySupport.getPropertyBool(PROP_EXPANDED); } @Override public void setExpanded(boolean b) { propertySupport.setPropertyBool(PROP_EXPANDED, b); } @Override public IGroupBoxUIFacade getUIFacade() { return m_uiFacade; } @Override public void setBackgroundImageName(String imageName) { propertySupport.setPropertyString(PROP_BACKGROUND_IMAGE_NAME, imageName); } @Override public String getBackgroundImageName() { return propertySupport.getPropertyString(PROP_BACKGROUND_IMAGE_NAME); } /** @since Build 178 */ @Override public void setBackgroundImageVerticalAlignment(int a) { propertySupport.setPropertyInt(PROP_BACKGROUND_IMAGE_VERTICAL_ALIGNMENT, a); } /** @since Build 178 */ @Override public int getBackgroundImageVerticalAlignment() { return propertySupport.getPropertyInt(PROP_BACKGROUND_IMAGE_VERTICAL_ALIGNMENT); } /** @since Build 178 */ @Override public void setBackgroundImageHorizontalAlignment(int a) { propertySupport.setPropertyInt(PROP_BACKGROUND_IMAGE_HORIZONTAL_ALIGNMENT, a); } /** @since Build 178 */ @Override public int getBackgroundImageHorizontalAlignment() { return propertySupport.getPropertyInt(PROP_BACKGROUND_IMAGE_HORIZONTAL_ALIGNMENT); } private class P_UIFacade implements IGroupBoxUIFacade { @Override public void setExpandedFromUI(boolean expanded) { setExpanded(expanded); } } protected static class LocalGroupBoxExtension<OWNER extends AbstractGroupBox> extends LocalCompositeFieldExtension<OWNER> implements IGroupBoxExtension<OWNER> { public LocalGroupBoxExtension(OWNER owner) { super(owner); } } @Override protected IGroupBoxExtension<? extends AbstractGroupBox> createLocalExtension() { return new LocalGroupBoxExtension<AbstractGroupBox>(this); } }
public class RwtScoutBrowserField extends RwtScoutValueFieldComposite<IBrowserField> implements IRwtScoutBrowserField { private static final IScoutLogger LOG = ScoutLogManager.getLogger(RwtScoutBrowserField.class); private String m_currentLocation; private BrowserExtension m_browserExtension; public RwtScoutBrowserField() {} @Override protected void initializeUi(Composite parent) { Composite container = getUiEnvironment().getFormToolkit().createComposite(parent); StatusLabelEx label = getUiEnvironment().getFormToolkit().createStatusLabel(container, getScoutObject()); Browser browser = getUiEnvironment().getFormToolkit().createBrowser(container, SWT.NONE); m_browserExtension = new BrowserExtension(browser); m_browserExtension.attach(); browser.addDisposeListener( new DisposeListener() { private static final long serialVersionUID = 1L; @Override public void widgetDisposed(DisposeEvent e) { m_browserExtension.detach(); } }); browser.addLocationListener( new LocationAdapter() { private static final long serialVersionUID = 1L; @Override public void changing(LocationEvent event) { event.doit = fireBeforeLocationChangedFromUi(event.location); } @Override public void changed(LocationEvent event) { fireAfterLocationChangedFromUi(event.location); } }); // setUiContainer(container); setUiLabel(label); setUiField(browser); // layout getUiContainer().setLayout(new LogicalGridLayout(1, 0)); } @Override public Browser getUiField() { return (Browser) super.getUiField(); } @Override protected void handleScoutPropertyChange(String name, Object newValue) { super.handleScoutPropertyChange(name, newValue); if (IBrowserField.PROP_LOCATION.equals(name)) { setLocationFromScout(); } } @Override protected void setValueFromScout() { setLocationFromScout(); } protected void setLocationFromScout() { m_browserExtension.clearResourceCache(); m_browserExtension.clearLocalHyperlinkCache(); String location = getScoutObject().getLocation(); RemoteFile r = getScoutObject().getValue(); if (location == null && r != null && r.exists()) { try { if (r.getName().matches(".*\\.(zip|jar)")) { location = registerResourcesInZip(r); } else { String content = IOUtility.getContent(r.getDecompressedReader()); content = m_browserExtension.adaptLocalHyperlinks(content, 1); location = m_browserExtension.addResource( r.getName(), new ByteArrayInputStream(content.getBytes("UTF-8"))); } // Prevent caching by making the request unique if (location != null) { location += "?nocache=" + System.currentTimeMillis(); } } catch (Throwable t) { LOG.error("preparing html content for " + r, t); } } m_currentLocation = location; if (m_currentLocation != null) { getUiField().setUrl(m_currentLocation); } else { getUiField().setText(""); } } private String registerResourcesInZip(RemoteFile zipFile) throws ProcessingException, IOException, UnsupportedEncodingException, FileNotFoundException { String location = null; File tempDir = IOUtility.createTempDirectory("browser"); try { zipFile.writeZipContentToDirectory(tempDir); String simpleName = zipFile.getName().replaceAll("\\.(zip|jar)", ".htm"); // rewrite local urls and register resource int prefixLen = tempDir.getAbsolutePath().length() + 1; for (File f : IOUtility.listFilesInSubtree(tempDir, null)) { if (f.isFile()) { String path = f.getAbsolutePath().substring(prefixLen); if (path.toLowerCase().matches(".*\\.(htm|html)")) { String content = IOUtility.getContent(new InputStreamReader(new FileInputStream(f), "UTF-8")); content = m_browserExtension.adaptLocalHyperlinks(content, 1); if (location == null && path.startsWith(simpleName)) { // this is the index.html location = m_browserExtension.addResource( simpleName, new ByteArrayInputStream(content.getBytes("UTF-8"))); } else { m_browserExtension.addResource( path, new ByteArrayInputStream(content.getBytes("UTF-8"))); } } else if (path.toLowerCase().matches(".*\\.(svg)")) { String content = IOUtility.getContent(new InputStreamReader(new FileInputStream(f))); content = m_browserExtension.adaptLocalHyperlinks(content, 1); m_browserExtension.addResource( path, new ByteArrayInputStream(content.getBytes("UTF-8"))); } else { m_browserExtension.addResource(path, new FileInputStream(f)); } } } } finally { if (tempDir != null) { IOUtility.deleteDirectory(tempDir); } } return location; } @Override protected void setEnabledFromScout(boolean b) { // nop } protected boolean fireBeforeLocationChangedFromUi(final String location) { final AtomicReference<Boolean> accept = new AtomicReference<Boolean>(); synchronized (accept) { // notify Scout Runnable t = new Runnable() { @Override public void run() { synchronized (accept) { accept.set( getScoutObject().getUIFacade().fireBeforeLocationChangedFromUI(location)); accept.notifyAll(); } } }; getUiEnvironment().invokeScoutLater(t, 0); // end notify // wait at most 10 seconds try { accept.wait(10000L); } catch (InterruptedException e) { // nop } } return accept.get() != null ? accept.get().booleanValue() : false; } protected void fireAfterLocationChangedFromUi(final String location) { // notify Scout Runnable t = new Runnable() { @Override public void run() { getScoutObject().getUIFacade().fireAfterLocationChangedFromUI(location); } }; getUiEnvironment().invokeScoutLater(t, 0); // end notify } }
/** * Sql SELECT statement for getting {@link LookupRow}s.<br> * * <p>The expected columns are * * <ul> * <li>Object key * <li>String text * <li>String iconId * <li>String tooltip * <li>String background color * <li>String foreground color * <li>String font * <li>Boolean enabled * <li>Object parentKey used in hierarchical structures to point to the parents primary key * <li>{@link TriState} active (0,1,null,...) see {@link TriState#parse(Object)} * </ul> * * <p>Valid bind names are: Object key, String text, String all, Object rec, {@link TriState} active * <br> * Valid xml tags are: <key>, <text>, <all>, <rec> */ public abstract class AbstractSqlLookupService<T> extends AbstractLookupService<T> { private static final Pattern REFUSING_ALL_TAGS_REGEX = Pattern.compile("<all>\\s*and\\s*([0-9]+)\\s*=\\s*([0-9]+)\\s*</all>", Pattern.DOTALL); private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractSqlLookupService.class); public AbstractSqlLookupService() {} /** Sql SELECT statement */ @ConfigProperty(ConfigProperty.SQL) @Order(10) protected String getConfiguredSqlSelect() { return null; } /** sort column 0-based. -1 if sort is done in sql. */ @ConfigProperty(ConfigProperty.INTEGER) @Order(20) protected int getConfiguredSortColumn() { return 1; } /** This method is called on server side to load lookup rows. */ @ConfigOperation @Order(10) protected List<ILookupRow<T>> execLoadLookupRows( String originalSql, String preprocessedSql, ILookupCall<T> call) throws ProcessingException { Object[][] data = SQL.selectLimited(preprocessedSql, call.getMaxRowCount(), call); if (getConfiguredSortColumn() >= 0) { sortData(data, getConfiguredSortColumn()); } try { Class<?> genericsParameterClass = Object.class; try { genericsParameterClass = TypeCastUtility.getGenericsParameterClass(getClass(), ILookupService.class); } catch (IllegalArgumentException e) { LOG.warn( "Unable to calculate type parameters for lookup service '" + getClass().getName() + "'. No key type validation will be performed."); } return createLookupRowArray(data, call, genericsParameterClass); } catch (IllegalArgumentException e) { throw new ProcessingException( "Unable to load lookup rows for lookup service '" + getClass().getName() + "'.", e); } } @Override public List<ILookupRow<T>> getDataByKey(ILookupCall<T> call) throws ProcessingException { String sql = getConfiguredSqlSelect(); return execLoadLookupRows(sql, filterSqlByKey(sql), call); } @Override public List<ILookupRow<T>> getDataByText(ILookupCall<T> call) throws ProcessingException { // change wildcards * in text to db specific wildcards if (call.getText() != null) { String s = call.getText(); String sqlWildcard = SERVICES.getService(ISqlService.class).getSqlStyle().getLikeWildcard(); call.setText(s.replaceAll("[*]", sqlWildcard)); } String sql = getConfiguredSqlSelect(); return execLoadLookupRows(sql, filterSqlByText(sql), call); } @Override public List<ILookupRow<T>> getDataByAll(ILookupCall<T> call) throws ProcessingException { String sql = getConfiguredSqlSelect(); if (containsRefusingAllTag(sql)) { throw new VetoException(ScoutTexts.get("SearchTextIsTooGeneral")); } List<ILookupRow<T>> rows = execLoadLookupRows(sql, filterSqlByAll(sql), call); return rows; } @Override public List<ILookupRow<T>> getDataByRec(ILookupCall<T> call) throws ProcessingException { String sql = getConfiguredSqlSelect(); return execLoadLookupRows(sql, filterSqlByRec(sql), call); } /** * Process xml tags.<br> * Keep content of "key" tag.<br> * Remove text,all,rec tags. */ protected String filterSqlByKey(String sqlSelect) { return StringUtility.removeTagBounds( StringUtility.removeTags(sqlSelect, new String[] {"text", "all", "rec"}), "key"); } /** * Process xml tags.<br> * Keep content of "text" tag.<br> * Remove key,all,rec tags. */ protected String filterSqlByText(String sqlSelect) { return StringUtility.removeTagBounds( StringUtility.removeTags(sqlSelect, new String[] {"key", "all", "rec"}), "text"); } /** * Process xml tags.<br> * Keep content of "all" tag.<br> * Remove key,text,rec tags. */ protected String filterSqlByAll(String sqlSelect) { return StringUtility.removeTagBounds( StringUtility.removeTags(sqlSelect, new String[] {"key", "text", "rec"}), "all"); } protected static boolean containsRefusingAllTag(String sqlSelect) { Matcher m = REFUSING_ALL_TAGS_REGEX.matcher(sqlSelect.toLowerCase()); if (m.find()) { if (!m.group(1).equals(m.group(2))) { return true; } } return false; } /** * Process xml tags.<br> * Keep content of "rec" tag.<br> * Remove key,text,all tags. */ protected String filterSqlByRec(String sqlSelect) { return StringUtility.removeTagBounds( StringUtility.removeTags(sqlSelect, new String[] {"key", "text", "all"}), "rec"); } }
/** * {@link Permissions} store per userId without any notifications. * * <p>Maintains a map of one {@link Permissions} object per userId (derived from their Subject, see * {@link IAccessControlService#getUserIdOfCurrentSubject()}). * * <p>The userId is case insensitive, case does not matter. * * @since 4.3.0 (Mars-M5) */ public class AccessControlStore { private static final IScoutLogger LOG = ScoutLogManager.getLogger(AccessControlStore.class); /** the internal store, the {@link String} used as key is always lower case */ private TTLCache<String /* userId */, Permissions> m_store; private Object m_storeLock; public AccessControlStore() { m_storeLock = new Object(); m_store = new TTLCache<String, Permissions>(3600000L); } /** @return the permission collection that is associated with the current subject */ public Permissions getPermissionsOfCurrentSubject() { String userId = SERVICES.getService(IAccessControlService.class).getUserIdOfCurrentSubject(); if (userId == null) { return null; } return getPermissions(userId); } /** * sets permission collection that is associated with the current subject * * @param p permission collection */ public void setPermissionsOfCurrentSubject(Permissions p) { String userId = SERVICES.getService(IAccessControlService.class).getUserIdOfCurrentSubject(); if (userId == null) { throw new SecurityException("userId is null"); } setPermissions(userId, p); } /** * @param userId of Subject * @return the permission collection that is associated with this userId, <code>null</code> if the * parameter is <code>null</code> */ public Permissions getPermissions(String userId) { if (userId == null) { return null; } synchronized (m_storeLock) { return m_store.get(userId.toLowerCase()); } } /** * associate a permission collection with this userId * * @param userId if userId is <code>null</code> the method does nothing */ public void setPermissions(String userId, Permissions p) { if (userId == null) { return; } synchronized (m_storeLock) { if (p == null) { p = new Permissions(); p.setReadOnly(); } m_store.put(userId.toLowerCase(), p); } } /** clears the cache */ public void clearCache() { clearCacheOfUserIds(getUserIds()); } /** * Clears the cache for a set of userIds and sends a notification for these users. * * @param userIds derived from the Subject, see{@link * IAccessControlService#getUserIdOfCurrentSubject()} */ public void clearCacheOfUserIds(Collection<String> userIds0) { Set<String> userIds = CollectionUtility.hashSetWithoutNullElements(userIds0); if (userIds.isEmpty()) { return; } synchronized (m_storeLock) { for (String userId : userIds) { if (userId != null) { m_store.remove(userId.toLowerCase()); } } } } public Collection<String> getUserIds() { synchronized (m_storeLock) { return CollectionUtility.hashSet(m_store.keySet()); } } }
class ConcurrencyQueue { private static final IScoutLogger LOG = ScoutLogManager.getLogger(ConcurrencyQueue.class); private static long seqNoProvider; private long m_seqNo; private Object m_queueChangeLock; private boolean m_closed; private String m_name; private String m_infoCached; private Object m_listLock = new Object(); private LinkedList<Runnable> m_list = new LinkedList<Runnable>(); private LinkedList<Runnable> m_dispatchingList = new LinkedList<Runnable>(); public ConcurrencyQueue(String name, Object queueChangeLock) { m_seqNo = seqNoProvider++; if (queueChangeLock == null) { queueChangeLock = new Object(); } m_queueChangeLock = queueChangeLock; m_name = name; updateInternalInfo(); } public boolean isEmpty() { synchronized (m_listLock) { return m_list.size() + m_dispatchingList.size() == 0; } } public void close() { m_closed = true; synchronized (m_listLock) { m_listLock.notifyAll(); } synchronized (m_queueChangeLock) { m_queueChangeLock.notifyAll(); } } public boolean isClosed() { return m_closed; } public void add(Runnable r) { if (r != null) { synchronized (m_listLock) { if (LOG.isDebugEnabled()) { LOG.debug(m_infoCached + " add: " + r); } m_list.add(r); updateInternalInfo(); m_listLock.notifyAll(); } synchronized (m_queueChangeLock) { m_queueChangeLock.notifyAll(); } } } /** @return true if element could be removed */ public boolean remove(Runnable r) { if (r != null) { boolean ok; synchronized (m_listLock) { ok = m_list.remove(r); updateInternalInfo(); m_listLock.notifyAll(); } synchronized (m_queueChangeLock) { m_queueChangeLock.notifyAll(); } return ok; } return false; } public boolean isPending(Runnable r) { if (r != null) { synchronized (m_listLock) { return m_dispatchingList.contains(r) || m_list.contains(r); } } return false; } /** does not block */ public boolean hasNext() { synchronized (m_listLock) { return !m_list.isEmpty(); } } public List<Runnable> removeAllJobs() { synchronized (m_listLock) { ArrayList<Runnable> a = new ArrayList<Runnable>(m_list); m_list.clear(); return a; } } /** block at most waitTime millis */ public boolean hasNext(long waitTime) { long deadline = System.currentTimeMillis() + waitTime; synchronized (m_listLock) { while (m_list.isEmpty()) { long dt = deadline - System.currentTimeMillis(); if (dt > 0) { try { m_listLock.wait(dt); } catch (InterruptedException e) { } } else { break; } } return !m_list.isEmpty(); } } public void dispatchNext() { Runnable r = null; synchronized (m_listLock) { if (!m_list.isEmpty()) { r = m_list.removeFirst(); m_dispatchingList.add(r); } } if (r != null) { try { long startTime = System.currentTimeMillis(); if (LOG.isDebugEnabled()) { LOG.debug(m_infoCached + " dispatchStart: " + r); } r.run(); if (LOG.isDebugEnabled()) { LOG.debug( m_infoCached + " dispatchEnd " + (System.currentTimeMillis() - startTime) + " ms: " + r); } } catch (Throwable t) { LOG.error(null, t); } synchronized (m_listLock) { m_dispatchingList.remove(r); updateInternalInfo(); m_listLock.notifyAll(); } synchronized (m_queueChangeLock) { m_queueChangeLock.notifyAll(); } } } private void updateInternalInfo() { int a = m_list.size(); int b = m_dispatchingList.size(); m_infoCached = m_name + "#" + m_seqNo + "[" + a + (b > 0 ? "+" + b : "") + " jobs]"; } @Override public String toString() { return m_infoCached; } }