/*
* 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;
}