Showing posts with label Eclipse RCP. Show all posts
Showing posts with label Eclipse RCP. Show all posts

Use Custom logging Formatter/Handler in Eclipse RCP


In my latest Eclipse RCP project, we use java.util.logging and want to add a custom Formatter in logging properties.

It works on IBM JDK 6.0, but doesn't work on Sun JDK, or any IBM previous JDK releases.Compared the source code of LogManager and Handler classes in Sun JDK or IBM old JDK releases, I figured out that this is because in IBM JDK 6.0, when to new a Formatter (Hanlder etc) instance, it use context ClassLoader (the ClassLoader of the method that called the caller) to load Formatter class:
Thread.currentThread().getContextClassLoader() But in old releases, it just use system classloader to load formatter class: ClassLoader.getSystemClassLoader().loadClass(val)
Of course, it can't find our custom Formatter class in system classloader, so it throws ClassNotFoundException.
The simple (not elegant way) is that when the application starts, configure jdk logging in AbstractUIPlugin subclass:

public class Activator extends AbstractUIPlugin  
{  
  public static final String PLUGIN_ID = "org.codeexample.myrcp"; //$NON-NLS-1$  
  public Activator(){}  
  public void start(BundleContext context) throws Exception  
  {  
   LogConfigurer.configureLogging();  
   final Logger logger = Logger.getLogger(Activator.class.getName());  
   // test logger  
   logger.warning("hello logger: " + new Date());  
   logger.throwing(Activator.class.getName(), "start", new RuntimeException("thrown exception"));  
   super.start(context);  
  }  
  public void stop(BundleContext context) throws Exception  
  {  
   super.stop(context);  
  }  
 }  
public class LogConfigurer { 
     public static String DATE_FOMAT = "yyyy-MM-dd hh:mm:ss.SSS"; 
     public static String LOG_DIRECTORY = Platform.getLocation() 
               .toPortableString() + IConstants.FILE_SEPARATOR + "logs"; 
     public static String LOG_PREFIX = "main"; 
     public static boolean configured = false; 
     public synchronized static void configureLogging() { 
          if (!configured) { 
               configured = true; 
               try { 
                    LogManager.getLogManager().readConfiguration( 
                              LogConfigurer.class 
                                        .getResourceAsStream("logging.properties")); 
                    File file = new File(LOG_DIRECTORY); 
                    if (!file.exists()) { 
                         file.mkdir(); 
                    } 
                    FileHandler fileHandler = new FileHandler(LOG_DIRECTORY 
                              + IConstants.FILE_SEPARATOR + LOG_PREFIX + ".log", true); 
                    fileHandler.setFormatter(new MySimpleFormatter()); 
                    fileHandler.setEncoding("UTF-8"); 
                    fileHandler.setLevel(Level.FINER); 
                    ConsoleHandler consoleHandler = new ConsoleHandler(); 
                    consoleHandler.setFormatter(new MySimpleFormatter()); 
                    consoleHandler.setEncoding("UTF-8"); 
                    consoleHandler.setLevel(Level.ALL); 
                    Logger parentLogger = Logger 
                              .getLogger("com.ibm.storage.ess.cli.wrapper"); 
                    parentLogger.addHandler(fileHandler); 
                    parentLogger.addHandler(consoleHandler); 
                    parentLogger.setLevel(Level.ALL); 
               } catch (Exception e) { 
                    Activator.logException(e); 
               } 
          } 
     } 
} 
/** 
 * The code is similar as JDK SimpleFormatter, just made a little change to 
 * record all message(including exception stack) in one line. 
 */ 
public class MySimpleFormatter extends Formatter { 
     Date dat = new Date(); 
     private final static String format = "{0,date," + LogConfigurer.DATE_FOMAT 
               + "}"; 
     private MessageFormat formatter; 
     private Object args[] = new Object[1]; 
     public static final String LINE_SEPARATOR = System 
               .getProperty("line.separator"); 
     private String separator = " ------ "; 
     public synchronized String format(LogRecord record) { 
          StringBuffer sb = new StringBuffer(); 
          // Minimize memory allocations here. 
          dat.setTime(record.getMillis()); 
          args[0] = dat; 
          StringBuffer text = new StringBuffer(); 
          if (formatter == null) { 
               formatter = new MessageFormat(format); 
          } 
          formatter.format(args, text, null); 
          sb.append(text); 
          sb.append(" "); 
          if (record.getSourceClassName() != null) { 
               sb.append(record.getSourceClassName()); 
          } else { 
               sb.append(record.getLoggerName()); 
          } 
          if (record.getSourceMethodName() != null) { 
               sb.append(" "); 
               sb.append(record.getSourceMethodName()); 
          } 
          sb.append(separator); 
          String message = formatMessage(record); 
          sb.append(record.getLevel().getLocalizedName()); 
          sb.append(": "); 
          sb.append(message); 
          if (record.getThrown() != null) { 
               sb.append(separator); 
               try { 
                    StringWriter sw = new StringWriter(); 
                    PrintWriter pw = new PrintWriter(sw); 
                    record.getThrown().printStackTrace(pw); 
                    pw.close(); 
                    String str = sw.toString(); 
                    String[] strs = str.split(IConstants.LINE_SEPARATOR); 
                    for (int i = 0; i < strs.length; i++) { 
                         sb.append(strs[i]); 
                         if (i != strs.length - 1) { 
                              sb.append(separator); 
                         } 
                    } 
               } catch (Exception ex) { 
               } 
          } 
          sb.append("\n"); 
          return sb.toString(); 
     } 
} 

Eclipse RCP Miscs Series 2


Eclipse RCP Miscs Series 2

Perspective listener
-- Define the behavior what to do when perspective is activated or changed.
IWorkbenchWindow.addPerspectiveListener(IPerspectiveListener listener) and removePerspectiveListener(IPerspectiveListener listener).

Allow user to bring job dialog back
After checked the Checkbox "always run in background", there would be no way to re-show it, so RCP application should define one preference to allow user to reshow the dialog.
    protected void createFieldEditors()
    {
       runInBackground = new BooleanFieldEditor(
           IPreferenceConstants.RUN_IN_BACKGROUND,
           "Always run in background",
           getFieldEditorParent());
       addField(runInBackground);
}
    public boolean performOk()
    {
       try
       {
           WorkbenchPlugin
               .getDefault()
               .getPreferenceStore()
               .setValue(IPreferenceConstants.RUN_IN_BACKGROUND, runInBackground.getBooleanValue());
       }
       catch (IOException e)
       {
           e.printStackTrace();
       }
       return super.performOk();
    }
ToolTip for TreeItem

Since SWT/JFace 3.3, your TreeViewer's lable provider can extend ColumnLabelProvider, and implement the cool getTooltip() methods, and enable it by ColumnViewerToolTipSupport.enableFor (viewer);

1. Outside of your rcp project, type
mvn3
org.sonatype.tycho:maven-tycho-plugin:generate-poms -DgroupId=se.mattiasholmqvist -Dtycho.targetPlatform=~/dev/eclipse-3.6.1-delta/
This will create a pom.xml for the current directory (parent project) and a pom.xml for each eclipse project.
2. Building the product
mvn3
clean package -Dtycho.targetPlatform=~/dev/eclipse-3.6.1-delta/

Export product to other platforms
1. Download and install Eclipse DelatPack
In the page, http://download.eclipse.org/eclipse/downloads/, search DeltaPack.
2. Configure org.sonatype.tycho/maven-osgi-packaging-plugin in pom.xml: set the environment values for the target platform.
You can get these values form the delta pack:
org.eclipse.equinox.launcher.${ws}.${os}.${arch}_1.1.0.v20100503
For instance, from
org.eclipse.equinox.launcher.motif.aix.ppc_1.1.0.v20100503, we can see to build a AIX product:
ws should be motif, os should be aix, arch should be ppc.


A concrete example:

Eclipse RCP Miscs Series 1


Eclipse RCP Miscs Series 1

API
Display.getCurrent().getActiveShell()
Display.getDefault().getActiveShell()
IWorkbenchWindow window
= HandlerUtil.getActiveWorkbenchWindow(event);
URL url
= Activator.getDefault().getBundle().getResource("log4j.properties"); PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView/findView(viewName);

Get current perspective
IPerspectiveDescriptor perspective=PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getPerspective();

Expand/Collapse a tree viewer
if (treeViewer.getExpandedState(firstElement))
{
    treeViewer.collapseToLevel(firstElement, AbstractTreeViewer.ALL_LEVELS);
}
else
{
    treeViewer.expandToLevel(firstElement, 1);
}
Enable Find/Replace Action
1. Register it in ApplicationActionBarAdvisor
    protected void makeActions(IWorkbenchWindow window) {
       register(ActionFactory.FIND.create(window));
    }
2. Add the command to the menu.
3. in the view:
public void createControl(Composite parent)
{
    FindReplaceAction action = new FindReplaceAction(Activator.getDefault().getResourceBundle(), "find", getSite()
        .getShell(), textViewer.getFindReplaceTarget());
    getSite().getActionBars().setGlobalActionHandler(ActionFactory.FIND.getId(), action);
}

PlatformUI.getWorkbench().showPerspective("com.frankdu.workbench.perspective_id", window);

PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("com.frankdu.workbench.view_id");
Hide editor in perspective
In perspective class:
public void createInitialLayout(IPageLayout layout)
{
    layout.setEditorAreaVisible(false);
}
In 3.5
org.eclipse.ui.IWorkbenchPage.hideEditor(IEditorReference) org.eclipse.ui.IWorkbenchPage.showEditor(IEditorReference) were introduced ... they can be used to hide editors when you switch perspectives (for example, in a perspective change listener)

Override initialize method in ApplicationWorkbenchAdvisor and add configurer.setSaveAndRestore(true);
public void initialize(final IWorkbenchConfigurer configurer)
{
    super.initialize(configurer);
    configurer.setSaveAndRestore(true);
}

menuContribution
The contributions are menu ID based, not menu path based.
menuContribution locationURI="menu:file?after=additions
 
menuContribution locationURI="menu:new?after=myGroup1"

Perspective Bar
It has to be enabled from the WorkbenchWindowAdvisor to appear.
configurer.setShowPerspectiveBar(true);
The perspective bar’s default location is just below the toolbar, but it can be placed in the top right or on the left using the
IWorkbenchPreferenceConstants.DOCK_PERSPECTIVE_BAR preference.
You can set this in the Hyperbola preferences.ini file as follows:
org.eclipse.ui/DOCK_PERSPECTIVE_BAR=TOP_RIGHT
Define what perspective would be shown in perspective bar.
org.eclipse.ui/PERSPECTIVE_BAR_EXTRAS=perspective_id

extension point="org.eclipse.ui.preferences"
  view
class="org.eclipse.ui.ExtensionFactory:newKeysPreferencePage"
      id="org.eclipsercp.hyperbola.preferences.keys"
      name="Keys"
extension
Try using the extension point "org.eclipse.ui.startup" and define a startup class for it. This class must implement IStartup, which defines earlyStartup(), as you probably know since you mentioned the method.

-consoleLog
-noExit
These can be added to launcher ini file, in Arguments tab if you start/debug rcp project in eclipse, or as program arugments in Launching tab of rcp product file.
The Eclipse runtime options

Press Alt+Shift+F1 to get information about the current running Eclipse plugin / data types / screen.
Press "Alt + Shift + F2" and select a menu to see who is contributing this menu.

In the file plugin.xml (tab dependencies), you can check if you have any dependency maintained which is actually not used, by selecting Dependency Analysis -> Find unused dependencies.

Labels

ANT (6) Algorithm (69) Algorithm Series (35) Android (7) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) JSON (7) Java (186) JavaScript (27) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) adsense (5) bat (8) regex (5) xml (5)