Package org.glassfish.uc.admingui

Source Code of org.glassfish.uc.admingui.UpdateCenterHandlers

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2009-2013 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.
*/

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package org.glassfish.uc.admingui;

import java.io.File;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.Map;
import java.util.Properties;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

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

import com.sun.pkg.client.Image;
import com.sun.pkg.client.Fmri;
import com.sun.pkg.client.LicenseAction;
import com.sun.pkg.client.Manifest;
import com.sun.pkg.client.SystemInfo;
import com.sun.pkg.client.SystemInfo.UpdateCheckFrequency;
import com.sun.pkg.client.Version;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpSession;


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

/**
*
* @author anilam
*/
public class UpdateCenterHandlers {

   @Handler(id="checkConnectionInfo",
        output={
        @HandlerOutput(name="connectionInfo", type=String.class),
        @HandlerOutput(name="noConnection", type=String.class)})
    public static void checkConnectionInfo(HandlerContext handlerCtx) {
        if (Boolean.TRUE.equals(GuiUtil.getSessionValue("_noNetwork"))){
            handlerCtx.setOutputValue("connectionInfo",  GuiUtil.getMessage(BUNDLE, "noNetworkDetected"));
            handlerCtx.setOutputValue("noConnection", "true");
        }
        /*
        else if ("true".equals(GuiUtil.getSessionValue("_doNotPing"))){
            handlerCtx.setOutputValue("connectionInfo",  GuiUtil.getMessage(BUNDLE, "noCheckPerformed"));
            handlerCtx.setOutputValue("noConnection", "true");
        }
         */
        else{
            handlerCtx.setOutputValue("noConnection", "false");
        }
    }


    @Handler(id="getInstalledPath",
        output={
        @HandlerOutput(name="result", type=String.class)})
    public static void getInstalledPath(HandlerContext handlerCtx) {
        Image image = getUpdateCenterImage();
        handlerCtx.setOutputValue("result"(image == null) ?
            GuiUtil.getMessage(BUNDLE, "updateCenter.NoImageDirectory") : image.getRootDirectory());
    }
   
   
    @Handler(id="getAuthority",
        output={
        @HandlerOutput(name="result", type=String.class)})
    public static void getAuthority(HandlerContext handlerCtx) {
        Image image = getUpdateCenterImage();
        handlerCtx.setOutputValue("result"(image == null) ? "" : image.getPreferredAuthorityName());
    }
   
   
    @Handler(id="getPkgDetailsInfo",
      input={
        @HandlerInput(name="fmriStr", type=String.class, required=true ),
        @HandlerInput(name="auth", type=String.class, required=true )},
        output={
        @HandlerOutput(name="details", type=java.util.Map.class)})
    public static void getPkgDetailsInfo(HandlerContext handlerCtx) {
        String fmriStr = (String)handlerCtx.getInputValue("fmriStr");
        //Called by the intiPage and don't need to process.  When we can use beforeCreate to do this, we can remove this check.
        if (fmriStr == null){
            handlerCtx.setOutputValue("details", new HashMap());
            return;
        }
        Fmri fmri = new Fmri(fmriStr);
        Map details = new HashMap()
        Image img = getUpdateCenterImage();
        try{
            details.put("pkgName", fmri.getName());
            details.put("uid", fmri.toString());
            details.put("version", getPkgVersion(fmri.getVersion()));
            details.put("date", fmri.getVersion().getPublishDate());
            details.put("auth", (String) handlerCtx.getInputValue("auth"));
            details.put("url", fmri.getURLPath());
            if (img != null){
                Manifest manifest = img.getManifest(fmri);
                details.put("category", getCategory(manifest));
                details.put("bytes", "" + manifest.getPackageSize() );
                details.put("pkgSize", getPkgSize(manifest));
                // look for description in the following order:
                // pkg.description, description_long, pkg.summary, description
                // since description_long and description has been deprecated.
                String desc = manifest.getAttribute(PKG_DESC);
                if (GuiUtil.isEmpty(desc)){
                    desc = manifest.getAttribute(DESC_LONG);
                    if (GuiUtil.isEmpty(desc)){
                        desc = manifest.getAttribute(PKG_SUMMARY);
                        if (GuiUtil.isEmpty(desc))
                            desc = manifest.getAttribute(DESC);
                    }
                }
                details.put("desc", desc);
            }
        }catch(Exception ex){
            ex.printStackTrace();
        }
        handlerCtx.setOutputValue("details", details);
       
    }

    private static String  getCategory(Manifest manifest){
        String attr = manifest.getAttribute(CATEGORY);
        //attr is of the form  scheme:catgory   refer to issue# 8494.
        int index = attr.indexOf(":");
        return (index==-1) ? attr : attr.substring(index+1);
    }
   
    @Handler(id="getUcList",
      input={
        @HandlerInput(name="state", type=String.class, required=true )},
        output={
        @HandlerOutput(name="result", type=java.util.List.class)})
    public static void getUcList(HandlerContext handlerCtx) {

        List result = new ArrayList();
        if (Boolean.TRUE.equals(GuiUtil.getSessionValue("_noNetwork"))){
            handlerCtx.setOutputValue("result", result);
            return;
        }
        try {
            Image img = getUpdateCenterImage();
            if (img == null){
                handlerCtx.setOutputValue("result", result);
                return;
            }
            String state= (String)handlerCtx.getInputValue("state");
            if (state.equals("update")){
                handlerCtx.setOutputValue("result", getUpdateDisplayList(img, false));
                return;
            }
           
            List<Fmri> displayList = null;
            if (state.equals("installed"))
                displayList = getInstalledList(img);
            else
            if (state.equals("addOn"))
                displayList = getAddOnList(img);

          if (displayList != null){
            for (Fmri fmri : displayList){
                Map oneRow = new HashMap();
                try{
                    Manifest manifest = img.getManifest(fmri);
                    oneRow.put("selected", false);
                    oneRow.put("fmri", fmri);
                    oneRow.put("fmriStr", fmri.toString());
                    putInfo(oneRow, "pkgName", fmri.getName());
                    putInfo(oneRow, "version", getPkgVersion(fmri.getVersion()));
                    putInfo(oneRow, "newVersion", "");
                    putInfo(oneRow, "category", getCategory(manifest));
                    putInfo(oneRow, "pkgSize", getPkgSize(manifest));
                    oneRow.put( "size", Integer.valueOf(manifest.getPackageSize()));
                    putInfo(oneRow, "auth", fmri.getAuthority());
                    String tooltip = manifest.getAttribute(PKG_SUMMARY);
                    if (GuiUtil.isEmpty(tooltip))
                        tooltip = manifest.getAttribute(DESC);
                    putInfo(oneRow, "tooltip", tooltip);
                    result.add(oneRow);
                }catch(Exception ex){
                    GuiUtil.getLogger().info("getUcList(): " +  ex.getLocalizedMessage());
                    if (GuiUtil.getLogger().isLoggable(Level.FINE)){
                        ex.printStackTrace();
                    }
                }
            }
          }
        }catch(Exception ex1){
            GuiUtil.getLogger().info("getUcList(): " +  ex1.getLocalizedMessage());
            if (GuiUtil.getLogger().isLoggable(Level.FINE)){
                ex1.printStackTrace();
            }
        }
        handlerCtx.setOutputValue("result", result);
    }
   
   
    @Handler(id="getAuthList",
        output={
        @HandlerOutput(name="result", type=java.util.List.class)})
    public static void getAuthList(HandlerContext handlerCtx) {
       
        List result = new ArrayList();
        try {
            Image image = getUpdateCenterImage();
            if (image == null){
                handlerCtx.setOutputValue("result", result);
                return;
            }
            String[] auths = image.getAuthorityNames();
            for(int i=0; i< auths.length; i++){
                Map oneRow = new HashMap();
                    oneRow.put("authName", auths[i]);
                    result.add(oneRow);
            }
        }catch(Exception ex1){
            ex1.printStackTrace();
        }
        handlerCtx.setOutputValue("result", result);
    }
   
   
    @Handler(id="getProxyInfo",
        output={
        @HandlerOutput(name="connection", type=String.class),
        @HandlerOutput(name="host", type=String.class),
        @HandlerOutput(name="port", type=String.class)}
        )
    public static void getProxyInfo(HandlerContext handlerCtx) {
       
        Proxy proxy = SystemInfo.getProxy();
        if (proxy != null){
            InetSocketAddress address = (InetSocketAddress) proxy.address();
            if (address != null){
                handlerCtx.setOutputValue("connection", "useProxy");
                handlerCtx.setOutputValue("host", address.getHostName());
                handlerCtx.setOutputValue("port", address.getPort());
                return;
            }
        }
        handlerCtx.setOutputValue("connection", "direct");
        handlerCtx.setOutputValue("host", "");
        handlerCtx.setOutputValue("port", "");
    }
   
    @Handler(id="setProxyInfo",
        input={
        @HandlerInput(name="connection", type=String.class),
        @HandlerInput(name="host", type=String.class),
        @HandlerInput(name="port", type=String.class)}
        )
    public static void setProxyInfo(HandlerContext handlerCtx) {
        String connection = (String)handlerCtx.getInputValue("connection");
        String host = (String)handlerCtx.getInputValue("host");
        String port = (String)handlerCtx.getInputValue("port");
        try{
            Image image = getUpdateCenterImage();
            if (image == null){
                String ucDir = (String)GuiUtil.getSessionValue("topDir");
                GuiUtil.handleError(handlerCtx,  GuiUtil.getMessage(BUNDLE, "NoImage", new String[]{ucDir}));
                return;
            }
            if (connection.equals("useProxy")){
                int portNo = Integer.parseInt(port);
                SocketAddress address = new InetSocketAddress(host, portNo);
                image.setProxy(new Proxy(Proxy.Type.HTTP, address));
                String url="http://"+host+":"+portNo;
                Properties prop = new Properties();
                prop.setProperty("proxy.URL", url);
                SystemInfo.initUpdateToolProps(prop);
            }else{
                image.setProxy(null);
                Properties prop = new Properties();
                prop.setProperty("proxy.URL", "");
                SystemInfo.initUpdateToolProps(prop);
            }
        }catch (Exception ex){
            GuiUtil.handleException(handlerCtx, ex);
        }
    }
                   
   
    private static void putInfo( Map oneRow, String key, String value){
        oneRow.put( key, GuiUtil.isEmpty(value) ? "" : value);
    }

    private static List<Fmri> getInstalledList(Image image){
        List<Image.FmriState> fList = image.getInventory(null, false);
        ArrayList<Fmri> result = new ArrayList();
        for(Image.FmriState fs: fList){
            result.add(fs.fmri);
        }
        return result;

    }

    /**
     * Returns true if f1 supersedes f2
     */
    private static boolean supersedes(Fmri f1, Fmri f2, String pAuth) {
        boolean f1Preferred = f1.getAuthority().equals(pAuth);
        boolean f2Preferred = f2.getAuthority().equals(pAuth);

        // If f1 is from the preferred authority and f2 is not, then
        // f1 supersedes.
        if (f1Preferred && ! f2Preferred) {
            return true;
        }

        // If f2 is from the preferred authority and f1 is not, then
        // f1 does not supersede
        if (f2Preferred && ! f1Preferred) {
            return false;
        }

        // Otherwise compare versions. f1 supersedes if it is a successor
        return f1.isSuccessor(f2);
    }

   
    private static List<Fmri> getAddOnList(Image image){
        List<String> installed = new ArrayList<String>();
        for (Image.FmriState each : image.getInventory(null, false)) {
            installed.add(each.fmri.getName());
        }
        String pAuth = image.getPreferredAuthorityName();
        SortedMap<String, Fmri> addOnMap = new TreeMap();
        for (Image.FmriState each : image.getInventory(null, true)) {
            Fmri fmri = each.fmri;
            // If this exact package is installed, or another version
            // of this package is installed, then skip it.
            if (each.installed || installed.contains(fmri.getName())) {
                continue;
            }

            if (addOnMap.containsKey(fmri.getName())) {
               // We have seen this package name already. See if this
               // version should replace the saved version.
               Fmri saved = addOnMap.get(fmri.getName());
               if (supersedes(fmri, saved, pAuth)) {
                   addOnMap.put(fmri.getName(), fmri);
               }
            } else {
               // We haven't seen this package name yet. Save fmri
               addOnMap.put(fmri.getName(), fmri);
            }

        }

        List<Fmri> result = new ArrayList();
        for(Fmri f: addOnMap.values()){
            result.add(f);
        }
        return result;
    }

    //If countOnly is set to true,  return a List that contains only one Integer that specifies the # of updates.
    //This is for displaying in the masthead
    //If countOnly is set to false, it will go through each package that has update available and return a list
    //suitable for displaying as a table row.
    private static List getUpdateDisplayList(Image image, boolean countOnly){
        List<Image.FmriState> installed = image.getInventory(null, false);
        Map<String, Fmri> updateListMap = new HashMap();
        List<String> nameList = new ArrayList();
        for(Image.FmriState fs: installed){
            if (fs.upgradable){
                Fmri fmri = fs.fmri;
                updateListMap.put(fmri.getName(),fmri);
                nameList.add(fmri.getName());
            }
        }
        List result = new ArrayList();
        String[] pkgsName = nameList.toArray(new String[nameList.size()]);
        try{
            Image.ImagePlan ip = image.makeInstallPlan(pkgsName, "list");
            Fmri[] proposed = ip.getProposedFmris();
            if (countOnly){
                result.add(Integer.valueOf(proposed.length));
                return result;
            }
            for( Fmri newPkg : proposed){
                Map oneRow = new HashMap();
                try{
                    String name = newPkg.getName();
                    Fmri oldPkg = updateListMap.get(name);
                    Manifest manifest = image.getManifest(newPkg);
                    int changedSize = manifest.getPackageSize() - image.getManifest(oldPkg).getPackageSize();
                    oneRow.put("selected", false);
                    oneRow.put("fmri", newPkg);
                    oneRow.put("fmriStr", newPkg.toString());
                    putInfo(oneRow, "pkgName", name);
                    putInfo(oneRow, "newVersion", getPkgVersion(newPkg.getVersion()));
                    putInfo(oneRow, "version", getPkgVersion(oldPkg.getVersion()));
                    putInfo(oneRow, "category", getCategory(manifest));
                    putInfo(oneRow, "pkgSize", convertSizeForDispay(changedSize));
                    oneRow.put( "size", Integer.valueOf(changedSize));
                    putInfo(oneRow, "auth", newPkg.getAuthority());
                    String tooltip = manifest.getAttribute(PKG_SUMMARY);
                    if (GuiUtil.isEmpty(tooltip))
                        tooltip = manifest.getAttribute(DESC);
                    putInfo(oneRow, "tooltip", tooltip);
                    result.add(oneRow);
                }catch(Exception ex){
                    ex.printStackTrace();
                }
            }
        }catch(Exception ex){
            ex.printStackTrace();
            if (countOnly){
                List tmpL = new ArrayList();
                tmpL.add(Integer.valueOf(-1));
                return tmpL;
            }
        }
       GuiUtil.setSessionValue("_updateCountMsg", GuiUtil.getMessage(UpdateCenterHandlers.BUNDLE, "msg.updatesAvailable", new String[]{""+result.size()}));
       return result;
    }
   
   
   
    @Handler(id="updateCenterProcess",
      input={
        @HandlerInput(name="action", type=String.class, required=true ),
        @HandlerInput(name="selectedRows", type=java.util.List.class, required=true )})
    public static void updateCenterProcess(HandlerContext handlerCtx) {
        Image image = getUpdateCenterImage();
        boolean install = false;
        String action= (String)handlerCtx.getInputValue("action");
        if (action.equals("install")) {
            install=true;
        }
        List obj = (List) handlerCtx.getInputValue("selectedRows");
        if (obj == null){
            //no row selected
            return;
        }
        List<Map> selectedRows = (List) obj;
        //do not use Fmri list to pass to installPackages, use String array to avoid UPDATECENTER2-2187
        String[] fmris = new String[selectedRows.size()];
        int i=0;
        try {
            for (Map oneRow : selectedRows) {
                fmris[i++]=((Fmri)oneRow.get("fmri")).toString();
            }
            if (install){
                image.installPackages(fmris);
                //updateCountInSession(image);   No need to update the update count since the count will not change.  Only installing new component is allowed.
            }else{
                image.uninstallPackages(fmris);
            }
            GuiUtil.setSessionValue("restartRequired", Boolean.TRUE);
        }catch(Exception ex){
            GuiUtil.handleException(handlerCtx, ex);
            ex.printStackTrace();
        }
    }
   
   // getLicenseText(selectedRows="#{selectedRows}" license=>$page{license});
     @Handler(id="getLicenseText",
      input={
        @HandlerInput(name="selectedRows", type=java.util.List.class, required=true)},
        output={
        @HandlerOutput(name="license", type=String.class),
        @HandlerOutput(name="hasLicense", type=Boolean.class)})
    public static void getLicenseText(HandlerContext handlerCtx) {
        
        List obj = (List) handlerCtx.getInputValue("selectedRows");
        Image image = getUpdateCenterImage();
        List<Map> selectedRows = (List) obj;
        try {
            StringBuffer allLicense = new StringBuffer();
            for (Map oneRow : selectedRows) {
                Fmri fmri = (Fmri)oneRow.get("fmri");
                allLicense.append(getLicense(image, fmri));
            }
            handlerCtx.setOutputValue("license", ""+allLicense);
            handlerCtx.setOutputValue("hasLicense", (allLicense.length() > 0));
        }catch(Exception ex){
            GuiUtil.handleException(handlerCtx, ex);
            //ex.printStackTrace();
        }
     }
       
    
    @Handler(id = "getUpdateComponentCount")
    public static void getUpdateComponentCount(HandlerContext handlerCtx) {

        boolean donotPing = false;
        //If user set NO_NETWORK system properties, don't try to do anything.
        boolean noNetwork = (Boolean) GuiUtil.getSessionValue("_noNetwork");
        if (noNetwork){
            GuiUtil.getLogger().info(GuiUtil.getMessage(BUNDLE,"noNetworkDetected"));
            donotPing = true;
        }else{
            UpdateCheckFrequency userPreference = SystemInfo.getUpdateCheckFrequency();
            if (userPreference == UpdateCheckFrequency.NEVER){
                GuiUtil.getLogger().info(GuiUtil.getMessage(BUNDLE,"noCheckPerformed"));
                GuiUtil.setSessionValue("_doNotPing", "true");
                donotPing = true;
            }
        }
        if (donotPing){
            GuiUtil.setSessionValue("_hideUpdateMsg", Boolean.TRUE);
            return;
        }
        GuiUtil.setSessionValue("_hideUpdateMsg", Boolean.FALSE);
        GuiUtil.setSessionValue("_updateCountMsg", "");
        UcThread thread = new UcThread((HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false));
        thread.start();
    }


     public static Integer updateCountInSession(Image image){
   Integer countInt = Integer.valueOf(-1);
   if (image != null){
      List list = getUpdateDisplayList(image, true);
      countInt = (Integer) list.get(0);
   }else{
      GuiUtil.getLogger().warning(GuiUtil.getMessage(BUNDLE, "cannotGetImage"));
   }
         return countInt;
     }
    
    private static String getLicense(Image img, Fmri fmri){
        StringBuffer licenseText = new StringBuffer();
        try{
            Manifest manifest = img.getManifest(fmri);
            List<LicenseAction> lla = manifest.getActionsByType(LicenseAction.class);
            for (LicenseAction la : lla) {
                licenseText.append("============= ").append(la.getName()).append(" ================\n");
                licenseText.append(fmri.toString());
                licenseText.append("\n\n");
                licenseText.append(la.getText());
                licenseText.append("\n\n");
            }
            return "" + licenseText;
        }catch(Exception ex){
            ex.printStackTrace();
        }
        return null;
    }
   
    private static String getPkgVersion(Version version){
        //The version format is release[,build_release]-branch:datetime, which is decomposed into three DotSequences and the datetime.
        //eg. 2.4.4,0-8.724:20080612T135341Z
       
        String dotSequence = version.getRelease().toString();
        String branch = version.getBranch().toString();
        return GuiUtil.isEmpty(branch) ? dotSequence : dotSequence+"-"+branch;
    }
   
    private static String getPkgSize(Manifest manifest){
        int size = manifest.getPackageSize();
        return convertSizeForDispay(size);
    }
   
    private static String convertSizeForDispay(int size){
        String sizep = (size <= MB) ?
            size/1024 + GuiUtil.getMessage(BUNDLE, "sizeKB") :
            size/MB + GuiUtil.getMessage(BUNDLE, "sizeMB";
        return sizep;
    }

    /* comment out un-used method.
    private static String getPkgDate(Version version){
        //TODO localize the date format
        int begin = version.toString().indexOf(":");
        int end = version.toString().indexOf("T");
        String dateStr = version.toString().substring(begin+1, end);
        String result = dateStr.substring(0,4) + "/" + dateStr.substring(4,6) + "/" + dateStr.substring(6,8);
        return result;
    }
     *
     */

   
    public static Image getUpdateCenterImage(){
        if (Boolean.TRUE.equals(GuiUtil.getSessionValue("_noNetwork"))){
            return null;
        }else{
         return getUpdateCenterImage((String)GuiUtil.getSessionValue("topDir"), false);
        }
    }

    public static Image getUpdateCenterImage(String ucDir, boolean force){
        Image image = null;
        try{
            image = new Image (new File (ucDir));
            if (force || (GuiUtil.getSessionValue(CATALOG_REFRESHED) == null)){
    image.refreshCatalogs();
    GuiUtil.setSessionValue(CATALOG_REFRESHED, "TRUE");
            }
        }catch(Exception ex){
            if(force && (image == null)){
                GuiUtil.getLogger().warning(GuiUtil.getMessage(BUNDLE, "NoImage", new String[]{ucDir}));
            }
        }
        return image;
    }

   
    final private static String CATEGORY = "info.classification";
    final private static String DESC_LONG = "description_long";
    final private static String PKG_DESC = "pkg.description";
    final private static String PKG_SUMMARY = "pkg.summary";
    final private static String DESC = "description";
    final private static String CATALOG_REFRESHED = "__gui_uc_catalog_refreshed";
    final public static String BUNDLE = "org.glassfish.updatecenter.admingui.Strings";
    final private static int MB = 1024*1024;

TOP

Related Classes of org.glassfish.uc.admingui.UpdateCenterHandlers

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.