Package org.glassfish.admingui.common.handlers

Source Code of org.glassfish.admingui.common.handlers.LogViewHandlers

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*
* CommonHandlers.java
*
* Created on August 30, 2006, 4:21 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package org.glassfish.admingui.common.handlers;

import com.sun.jsftemplating.annotation.Handler;
import com.sun.jsftemplating.annotation.HandlerInput;
import com.sun.jsftemplating.annotation.HandlerOutput;
import com.sun.jsftemplating.layout.descriptors.handler.HandlerContext;
import com.sun.jsftemplating.util.Util;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Level;

import org.glassfish.admingui.common.util.GuiUtil;


public class LogViewHandlers {

    /** Creates a new instance of LogViewHandlers */
    public LogViewHandlers() {
    }

    /**
     *  <p> This handler creates a Map&lt;String, String&gt; which contains
     *      the QUERY_STRING parameters that should be passed to the REST
     *      logging endpoint to make a query with the given constraints.</p>
     *
     *  @param  context  The HandlerContext.
     */
    @Handler(id="gf.getLogQueryAttributes",
        input={
            @HandlerInput(name="InstanceName", type=String.class, required=true),
            @HandlerInput(name="LogFileName", type=String.class, required=true),
            @HandlerInput(name="LogLevel", type=String.class, required=true),
            @HandlerInput(name="FromRecord", type=Integer.class),
            @HandlerInput(name="AfterRecord", type=Boolean.class),
            @HandlerInput(name="DateEnabled", type=String.class),
            @HandlerInput(name="FromDate", type=Object.class),
            @HandlerInput(name="FromTime", type=Object.class),
            @HandlerInput(name="ToDate", type=Object.class),
            @HandlerInput(name="ToTime", type=Object.class),
            @HandlerInput(name="Loggers", type=Object.class),
            @HandlerInput(name="CustomLoggers", type=Object.class),
            @HandlerInput(name="anySearch", type = String.class),
            @HandlerInput(name="NumToDisplay", type=Integer.class),
            @HandlerInput(name="OnlyLevel", type=Boolean.class, defaultValue="false"),
            @HandlerInput(name="LogDateSortDirection", type=Boolean.class)},
        output={
            @HandlerOutput(name="attributes", type=Map.class)})
    public static void getLogQueryAttributes(HandlerContext handlerCtx) {
  // Create a Map to hold the attributes
        Map<String, Object> attMap = new HashMap<String, Object>();

        // Attempt to read values passed in
        String logFileName = (String) handlerCtx.getInputValue("LogFileName");
        Integer fromRecord = (Integer) handlerCtx.getInputValue("FromRecord");
        Boolean after = (Boolean) handlerCtx.getInputValue("AfterRecord");
        String dateEnabledString = (String) handlerCtx.getInputValue("DateEnabled");
        Object fromDate = handlerCtx.getInputValue("FromDate");
        Object fromTime = handlerCtx.getInputValue("FromTime");
        Object toDate = handlerCtx.getInputValue("ToDate");
        Object toTime = handlerCtx.getInputValue("ToTime");
        Object loggers = handlerCtx.getInputValue("Loggers");
        String logLevel = (String) handlerCtx.getInputValue("LogLevel");
        Object customLoggers = handlerCtx.getInputValue("CustomLoggers");
        String anySearch = (String) handlerCtx.getInputValue("anySearch");
        Integer numberToDisplay = (Integer) handlerCtx.getInputValue("NumToDisplay");
        Boolean onlyLevel = (Boolean) handlerCtx.getInputValue("OnlyLevel");
        Boolean direction = (Boolean) handlerCtx.getInputValue("LogDateSortDirection");
        String instanceName = (String) handlerCtx.getInputValue("InstanceName");

        notNullStringPut(attMap, "instanceName", instanceName);
        Date from = null, to = null;

        if ((instanceName != null)) {
                  notNullStringPut(attMap, "instanceName", instanceName);
            if (logFileName != null) {
                // Convert Date/Time fields
                if ((dateEnabledString != null) &&
                        ("enabled".equalsIgnoreCase(dateEnabledString)
                        || "true".equalsIgnoreCase(dateEnabledString)))  {
                    // Date is enabled, figure out what the values are
                    from = convertDateTime(handlerCtx, fromDate, fromTime);
                    to = convertDateTime(handlerCtx, toDate, toTime);
                    if ((from == null)) {
                        GuiUtil.handleError(handlerCtx, "Specific Date Range was chosen, however, date fields are incomplete.");
                    }
                    if (to != null && from != null) {
                        if (from.after(to)) {
                            GuiUtil.handleError(handlerCtx, "Timestamp value of 'From: ' field " + fromDate +
                                    " must not be greater than 'To: ' field value " + toDate);
                        }
                    }
                } else {
                    // Date not enabled, ignore from/to dates
                    from = null;
                    to = null;
                }

                if ((logLevel != null) && (logLevel.trim().length() == 0)) {
                    logLevel = null;
                }

                // Convert module array to List
                //List moduleList = null;
                //Set moduleList = new HashSet();
                Set moduleList = null;
                if (loggers != null) {
                    int len = ((Object[]) loggers).length;
                    if (len > 0) {
                        moduleList = new HashSet();
                        Object val;
                        for (int count = 0; count < len; count++) {
                            val = (((Object[]) loggers)[count]);
                            if ((val == null) || (val.toString().trim().length() == 0)) {
                                continue;
                            }
                            moduleList.add(val);
                        }
                    }
                }

                // Add custom loggers
                if ((customLoggers != null) &&
                        (customLoggers.toString().trim().length() != 0)) {
                    StringTokenizer tok = new StringTokenizer(
                            customLoggers.toString(),
                            CUSTOM_LOGGER_DELIMITERS);
                    String token;
                    if (moduleList == null) {
                        moduleList = new HashSet();
                    }

                    while (tok.hasMoreTokens()) {
                        token = tok.nextToken();
                        if ((token == null) || (token.length() == 0)) {
                            continue;
                        }
                        moduleList.add(token);
                    }
                }

                // Get the number to Display
                if (numberToDisplay == null) {
                    numberToDisplay = DEFAULT_NUMBER_TO_DISPLAY;
                }

                // Get the direction
                if (direction == null) {
                    direction = Boolean.FALSE;
                }

                // Get AfterRecord flag
                if (after == null) {
                    // Not supplied, use direction
                    after = direction;
                }


                notNullStringPut(attMap, "logFileName", logFileName);
                notNullStringPut(attMap, "startIndex", fromRecord);
                notNullStringPut(attMap, "searchForward", after);//direction
                notNullStringPut(attMap, "maximumNumberOfResults", numberToDisplay);
                notNullStringPut(attMap, "onlyLevel", onlyLevel);

                if (from != null)
                    notNullStringPut(attMap,"fromTime", Long.valueOf(from.getTime()));
                if (to != null)
                    notNullStringPut(attMap, "toTime", Long.valueOf(to.getTime()));
                notNullStringPut(attMap, "anySearch", anySearch);
                notNullStringPut(attMap, "logLevel", logLevel);
                notNullStringPut(attMap, "instanceName", instanceName);
                notNullStringPut(attMap, "logFileRefresh", "true");
                if (moduleList != null) {
                    attMap.put("listOfModules", moduleList);
                }
                //notNullStringPut(attMap, "logFileRefresh", logFileName);
            }
        }
        handlerCtx.setOutputValue("attributes", attMap);
    }

    /**
     *  <p> This handler creates a Map&lt;String, String&gt; which contains
     *      the QUERY_STRING parameters that should be passed to the REST
     *      logging endpoint to make a query with the given constraints.</p>
     *
     *  @param  context  The HandlerContext.
     */
    @Handler(id="gf.processLogRecords",
        input={
            @HandlerInput(name="logRecords", type=List.class, required=true),
            @HandlerInput(name="truncate", type=Boolean.class, defaultValue="true"),
            @HandlerInput(name="truncateLength", type=Integer.class, defaultValue="100")},
  output={
            @HandlerOutput(name="result", type=List.class),
            @HandlerOutput(name="firstRecord", type=Integer.class),
            @HandlerOutput(name="lastRecord", type=Integer.class)})
    public static void processLogRecords(HandlerContext handlerCtx) {
  // Get the input...
  List<Map<String, Object>> records = (List<Map<String, Object>>)
    handlerCtx.getInputValue("logRecords");
  if (records != null) {
    // Make sure there's something to do...
      boolean truncate = (Boolean) handlerCtx.getInputValue("truncate");
      int truncLen = (Integer) handlerCtx.getInputValue("truncateLength");
      Locale locale = GuiUtil.getLocale();

      // Loop through the records...
      for (Map<String, Object> record : records) {
    record.put("dateTime",
        formatDateForDisplay(locale, new Date(new Long(
          record.get("loggedDateTimeInMS").toString()))));
      /*
    // FIXME: Should we add this code back in?  It was not being
    // FIXME: used in the current version.
    String msgId = (String) row.getMessageID();
    String level = (String) row.getLevel();
    String moduleName = (String)row.getModule();
    //only SEVERE msg provoides diagnostic info.
    if (level.equalsIgnoreCase("severe")) {
        // NOTE: Image name/location is hard-coded
        record.put("levelImage", GuiUtil.getMessage("common.errorGif"));
        record.put(SHOW_LEVEL_IMAGE, new Boolean(true));
        record.put("diagnosticCauses", getDiagnosticCauses(handlerCtx, msgId, moduleName));
        record.put("diagnosticChecks", getDiagnosticChecks(handlerCtx, msgId, moduleName));
    //                        record.put("diagnosticURI", getDiagnosticURI(handlerCtx, msgId));
    } else {
        record.put(SHOW_LEVEL_IMAGE, new Boolean(false));
        record.put("diagnostic", "");
    }
    record.put("level", level);
    record.put("productName", row.getProductName());
    record.put("logger", moduleName);
    */
    String message = ((String) record.get("Message")).trim();
    if (truncate && (message.length() > truncLen)) {
        message = message.substring(0, truncLen).concat("...\n");
    }
    record.put("Message", Util.htmlEscape(message));
      }
  }

  // Set the first / last record numbers as attributes
  if ((records != null) && (records.size() > 0)) {
      handlerCtx.setOutputValue("firstRecord", records.get(0).get("recordNumber"));
      handlerCtx.setOutputValue("lastRecord", records.get(records.size()-1).get("recordNumber"));
      //hasResults = true;
  } else {
      handlerCtx.setOutputValue("firstRecord", "-1");
      handlerCtx.setOutputValue("lastRecord", "-1");
  }
  handlerCtx.setOutputValue("result", records);
    }

    /**
     *  Utility for adding non-null values to the map as a String.
     */
    private static void notNullStringPut(Map<String, Object> map, String key, Object val) {
  if (val != null) {
      map.put(key, val.toString());
  }
    }

    /**
     *  This method converts a date/time string to a Date.
     *
     *  @param  request  The ServletRequest
     *  @param  date  The date as a String (or the date/time as a Date)
     *  @param  time  The time as a String (or null)
     *  @param  vd  The ViewDescriptor (for exception handling)
     *  @param  view  The View (for exception handling)
     */
    protected static Date convertDateTime(HandlerContext handlerCtx, Object date, Object time) {
      // If Date is already a Date, then do nothing
  if (date instanceof Date) {
      return (Date)date;
  }
  // If Date is null or empty, return null
  if ((date == null) || (date.toString().trim().length() == 0)) {
      return null;
  }

  // Get the date / time string
        if((time != null) && (time.toString().trim().length() == 0)) {
      time = null;
  }
  String dateTime = date.toString()+
      ((time == null) ? "" : (" "+time.toString()));
  DateFormat df = DateFormat.getDateInstance(
      DateFormat.SHORT, GuiUtil.getLocale());
  if ((time != null) && (df instanceof SimpleDateFormat)) {
      SimpleDateFormat fmt = (SimpleDateFormat)df;
      String formatPrefix = fmt.toLocalizedPattern();
      try {
    // Try w/ HH:mm:ss.SSS
    date = parseDateString(
        fmt, formatPrefix+TIME_FORMAT, dateTime);
      } catch (ParseException ex) {
    try {
        // Try w/ HH:mm:ss
        date = parseDateString(
      fmt, formatPrefix+TIME_FORMAT_2, dateTime);
    } catch (ParseException ex2) {
        try {
      // Try w/ HH:mm
      date = parseDateString(
          fmt, formatPrefix+TIME_FORMAT_3, dateTime);
        } catch (ParseException ex3) {
      GuiUtil.handleError(handlerCtx, "Unable to parse Date/Time: '"+dateTime+"'.");
        }
    }
      }
  } else if (time != null) {
      // I don't think this ever happens
      df = DateFormat.getDateTimeInstance(
    DateFormat.SHORT, DateFormat.LONG, GuiUtil.getLocale());
      try {
    date = df.parse(dateTime);
      } catch (ParseException ex) {
    GuiUtil.handleError(handlerCtx, "Unable to parse Date/Time: '"+dateTime+"'.");
      }
  } else {
      try {
    date = df.parse(dateTime);
      } catch (ParseException ex) {
    GuiUtil.handleError(handlerCtx, "Unable to parse Date/Time: '"+dateTime+"'.");
      }
  }

  // Return the result
        Date convertDate = null;
        try {
            convertDate = (Date)date;
        } catch (Exception ex) {
            convertDate = null;
        }
        return convertDate;
    }

    /**
     *  This method simply takes the given SimpleDateFormat and parses the
     *  given String after applying the given format String.
     */
    private  static Date parseDateString(SimpleDateFormat fmt, String format, String dateTime) throws ParseException {
  fmt.applyLocalizedPattern(format);
  return fmt.parse(dateTime);
    }

    /**
     *  This method formats a log file date to a more readable date (based on
     *  locale).
     */
    public static String formatDateForDisplay(Locale locale, Date date) {
  DateFormat dateFormat = DateFormat.getDateInstance(
      DateFormat.MEDIUM, locale);
  if (dateFormat instanceof SimpleDateFormat) {
      SimpleDateFormat fmt = (SimpleDateFormat)dateFormat;
      fmt.applyLocalizedPattern(fmt.toLocalizedPattern()+TIME_FORMAT);
      return fmt.format(date);
  } else {
      dateFormat = DateFormat.getDateTimeInstance(
    DateFormat.MEDIUM, DateFormat.LONG, locale);
      return dateFormat.format(date);
  }
    }


    /**
     *  <p> This handler returns the first and last log record.</p>
     *
     *  <p> Output value: "LogFileNames" -- Type: <code>java.util.SelectItem</code>
     *
     *  @param  context The HandlerContext.
     */
    @Handler(id="getFirstLastRecord",
        input={
      @HandlerInput(name="FirstRecord", type=String.class, required=true),
      @HandlerInput(name="LastRecord", type=String.class, required=true)},
        output={
            @HandlerOutput(name="First", type=String.class),
            @HandlerOutput(name="Last", type=String.class)})
    public static void getFirstLastRecord(HandlerContext handlerCtx) {
  // Get the first/last row numbers
  String firstLogRow = (String)handlerCtx.getInputValue("FirstRecord");
  String lastLogRow = (String)handlerCtx.getInputValue("LastRecord");
        if (firstLogRow == null) {
            firstLogRow="0";
  }
        if (lastLogRow == null) {
            lastLogRow="0";
  }
  int firstRow = 0;
  try {
      firstRow = Integer.parseInt(firstLogRow);
      int lastRow = Integer.parseInt(lastLogRow);
      if (firstRow > lastRow) {
    String temp = firstLogRow;
    firstLogRow = lastLogRow;
    lastLogRow = temp;
      }
            handlerCtx.setOutputValue("First", firstLogRow);
            handlerCtx.setOutputValue("Last", lastLogRow);
  } catch (NumberFormatException ex) {
      // ignore
  }
    }

        /**
     *  This method formats the diagnostic to be displayed for HTML
     *  Add '<br>' to each elements of the ArrayList and returns the String.
     */
    protected static String formatArrayForDisplay(String[] diag) {
        if ((diag == null) || (diag.length == 0)) {
      return "";
  }
        StringBuilder buf = new StringBuilder("<br>");
        for(int i=0; i<diag.length; i++){
            buf.append( (String)diag[i]);
      buf.append("<br>");
        }
        return buf.toString();
    }

    /**
     *  <P>This method puts the current time (as a String) in the desired
     *  attribute.  The result attribute must be specified via an attribute
     *  named "getTimeResultAttribute"</P>
     */
   @Handler(id="getTime",
        output={
            @HandlerOutput(name="Time", type=String.class)})
    public void getTime(HandlerContext handlerCtx) {
        try{
  DateFormat df = DateFormat.getTimeInstance(
      DateFormat.SHORT, GuiUtil.getLocale());
  ((SimpleDateFormat)df).applyLocalizedPattern(TIME_FORMAT);

  // Set the return value
  handlerCtx.setOutputValue("Time", df.format(new Date()));
        }catch(Exception ex){
            GuiUtil.handleException(handlerCtx, ex);
        }
    }

    /**
     *  <P>This method returns the current date (as a String).  The DATE_FORMAT
     *  must be specified, if it is not this method will fail.  You may set it
     *  to "short", "medium", "long", or "FULL".</P>
     *
     *  <P>If you do not set it to one of these values, you may set it to a
     *  valid format string.</P>
     */
    @Handler(id="getDate",
        input={
            @HandlerInput(name="DateFormat", type=String.class, required=true)},
        output={
            @HandlerOutput(name="Date", type=String.class)})
    public void getDate(HandlerContext handlerCtx) {
      // Get the required attribute
  String formatString = (String)handlerCtx.getInputValue("DateFormat");

  // Get the type
  int formatType = -1;
  if (formatString.equals(GET_DATE_SHORT)) {
      formatType = DateFormat.SHORT;
  } else if (formatString.equals(GET_DATE_MEDIUM)) {
      formatType = DateFormat.MEDIUM;
  } else if (formatString.equals(GET_DATE_LONG)) {
      formatType = DateFormat.LONG;
  } else if (formatString.equals(GET_DATE_FULL)) {
      formatType = DateFormat.FULL;
  }
  DateFormat df = null;
  if (formatType == -1) {
      df = DateFormat.getDateInstance(
    DateFormat.SHORT, GuiUtil.getLocale());
      ((SimpleDateFormat)df).applyLocalizedPattern(formatString);
  } else {
      df = DateFormat.getDateInstance(
    formatType, GuiUtil.getLocale());
  }

  // Set the return value
  handlerCtx.setOutputValue("Date", df.format(new Date()));
    }

    /**
     *  <P>This method returns the formatted date (as a String). </P>
     *
     */
    @Handler(id="getFormattedDateTime",
        input={
            @HandlerInput(name="Timestamp", type=String.class, required=true),
            @HandlerInput(name="AddHour", type=Boolean.class)},
        output={
            @HandlerOutput(name="Time", type=String.class),
            @HandlerOutput(name="Date", type=String.class)})
    public void getFormattedDateTime(HandlerContext handlerCtx) {
          String timeStamp = (String) handlerCtx.getInputValue("Timestamp");
          Boolean addHour = (Boolean) handlerCtx.getInputValue("AddHour");
          Date date = null;
          if ((timeStamp == null) || "".equals(timeStamp)) {
        date = new Date(System.currentTimeMillis());
          } else {
              try{
                  if (addHour != null) {
                      date = new Date(Long.parseLong(timeStamp) + ONE_HOUR);
                  } else {
                      date = new Date(Long.parseLong(timeStamp));
                  }
              }catch(Exception ex){
                  GuiUtil.getLogger().info(GuiUtil.getCommonMessage("log.error.dateFormat") + ex.getLocalizedMessage());
                  if (GuiUtil.getLogger().isLoggable(Level.FINE)){
                        ex.printStackTrace();
                  }
                  date = new Date(System.currentTimeMillis());
              }
          }
          DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, GuiUtil.getLocale());
          DateFormat tf = DateFormat.getTimeInstance(DateFormat.MEDIUM, GuiUtil.getLocale());
          ((SimpleDateFormat)tf).applyLocalizedPattern(" HH:mm:ss.SSS");

          String ftime = tf.format(date);
          String fdate = df.format(date);
          handlerCtx.setOutputValue("Time", ftime);
          handlerCtx.setOutputValue("Date", fdate);
       }


    /**
     *  This defines the short date format, used by DATE_FORMAT. ("short")
     */
    public static final String GET_DATE_SHORT = "short";

    /**
     *  This defines the medium date format, used by DATE_FORMAT. ("medium")
     */
    public static final String GET_DATE_MEDIUM = "medium";

    /**
     *  This defines the long date format, used by DATE_FORMAT. ("long")
     */
    public static final String GET_DATE_LONG = "long";

    /**
     *  This defines the full date format, used by DATE_FORMAT. ("full")
     */
    public static final String GET_DATE_FULL = "full";


    /**
     *  This specifies how TIME fields are input and displayed.  We need to do
     *  this in order to get a display/input that works with milliseconds.
     *  Perhaps in the future we may want to just append the milliseconds?
     */
    public static final String TIME_FORMAT = " HH:mm:ss.SSS";
    public static final String TIME_FORMAT_2 = " HH:mm:ss";
    public static final String TIME_FORMAT_3 = " HH:mm";


    /**
     *  If the number to display is not specified, this value will be used
     *  (40).
     */
    public static final Integer DEFAULT_NUMBER_TO_DISPLAY = Integer.valueOf(40);

    /**
     *
     */
    public static final String FIRST_LOG_ROW = "firstLogRow";

    public static final int FROM_RECORD = 0;

    /**
     *
     */
    public static final String LAST_LOG_ROW = "lastLogRow";

   /**
     *  The following constant defines the valid delimiters that can be used
     *  to seperate custom loggers on input. (" \t\n\r\f,;:")
     */
    public static final String CUSTOM_LOGGER_DELIMITERS = " \t\n\r\f,;:";
    /**
     *  The following constant defines the valid delimiters that can be used
     *  to seperate nvp entries on input. (" \t\n\r\f,;:")
     */
    public static final String NVP_DELIMITERS = " \t\n\r\f,;:";
    /**
     *  This is the delimiter between the property name and property value.
     */
    public static final char EQUALS = '=';
    /**
     *  This model key is set by the filter method, it is true if a
     *  level image should be displayed.
     */
    public static final String SHOW_LEVEL_IMAGE = "showLevelImage";

    /**
     *  This is the root directory of the alert images
     */
    public static final String LEVEL_IMAGE_ROOT =
  "/com_sun_web_ui/images/alerts/";

    public static final long ONE_HOUR = (1000 /* ms */) * (60 /* sec */) * (60 /* min */);
TOP

Related Classes of org.glassfish.admingui.common.handlers.LogViewHandlers

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.