/*
* Licensed to the Apache Software Foundation ( ASF ) under one
* or more contributor license agreements . See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership . The ASF licenses this file
* to you under the Apache License , Version 2 . 0 ( the
* " License " ) ; you may not use this file except in compliance
* with the License . You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing ,
* software distributed under the License is distributed on an
* " AS IS " BASIS , WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND , either express or implied . See the License for the
* specific language governing permissions and limitations
* under the License .
*/
package org.netbeans.nbbuild;
import java.awt.Dimension;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.FileSet;
/**
* Task for copying out icons from NetBeans projects . It creates paralel directory
* structure in destdir with only copied icons . It creates index . html page that
* lists all found icons and group them according to nb modules . Icons are considered
* images with dimensions 8 x8 , 16 x16 , 24 x24 , 32 x32 of type PNG or GIF .
* Inclusion filter for images in each module is given by attribute ' iconincludes ' ,
* default inclusion filter is all gifs and pngs under src folder . Exclusion filter
* is defined by attribute ' iconexcludes ' . Filters are regular ant inclusion and
* exclusion filters . Task tries to find all nb modules up to depth defined by
* ' depth ' attribute ( default is 4 ) in the nbsrcroot . Modules without icons are
* not listed by default , they can be shown by setting attribute ' showempty ' to true .
*
* Required attributes are :
* nbsrcroot . . . root of NetBeans Hg checkout
* destdir . . . dir for copying icons
*
* @ author Milan Kubec
*/
public class CopyIcons extends MatchingTask {
private int depth = 0 ;
private List<File> projectDirList = new ArrayList<>();
private List<ProjectIconInfo> prjIconInfoList = new ArrayList<>();
File baseDir = null ;
public void setNbsrcroot(File f) {
baseDir = f;
}
File destDir = null ;
public void setDestdir(File f) {
destDir = f;
}
int userDepth = 2 ;
public void setDepth(int n) {
userDepth = n;
}
String iconIncludes = "src/**/*.png,src/**/*.gif";
public void setIconincludes(String s) {
iconIncludes = s;
}
String iconExcludes = "" ;
public void setIconexcludes(String s) {
iconExcludes = s;
}
String prjIncludes = "" ;
public void setPrjincludes(String s) {
prjIncludes = s;
}
String prjExcludes = "" ;
public void setPrjExcludes(String s) {
prjExcludes = s;
}
boolean showEmpty = false ;
public void setShowempty(boolean b) {
showEmpty = b;
}
public void execute() throws BuildException {
if (baseDir == null || destDir == null ) {
log("Nbsrcroot or destdir are not specified." );
return ;
}
scanForProjectDirs(baseDir);
for (Iterator<File> iter = projectDirList.iterator(); iter.hasNext(); ) {
File f = iter.next();
processProjectDir(f);
}
copyToDestDir(prjIconInfoList);
dumpListToHTML(prjIconInfoList);
}
private ImageInfo readImageInfo(File fl) throws IOException {
Dimension dim = null ;
ImageInfo imageInfo = null ;
try (ByteArrayInputStream bais = readSomeBytes(fl)) {
if (isGIF(bais)) {
imageInfo = new ImageInfo(readGIFDimension(bais), ImageInfo.GIF);
} else if (isPNG(bais)) {
imageInfo = new ImageInfo(readPNGDimension(bais), ImageInfo.PNG);
}
} catch (IOException ex) {
ex.printStackTrace();
}
return imageInfo;
}
private ByteArrayInputStream readSomeBytes(File fl) throws IOException {
byte buffer[] = new byte [30 ];
FileInputStream fis = null ;
fis = new FileInputStream(fl);
fis.read(buffer);
fis.close();
return new ByteArrayInputStream(buffer);
}
private boolean isGIF(InputStream is) throws IOException {
is.reset();
byte buf[];
is.read(buf = new byte [3 ]);
int signatureBuffer[] = parseUnsigned(buf);
if (((char ) signatureBuffer[0 ] == 'G' ) &&
((char ) signatureBuffer[1 ] == 'I' ) &&
((char ) signatureBuffer[2 ] == 'F' )) {
return true ;
}
return false ;
}
private boolean isPNG(InputStream is) throws IOException {
is.reset();
byte buf[];
is.read(buf = new byte [8 ]);
int signatureBuffer[] = parseUnsigned(buf);
if ((signatureBuffer[0 ] == 137 ) && // PNG signature
(signatureBuffer[1 ] == 80 ) &&
(signatureBuffer[2 ] == 78 ) &&
(signatureBuffer[3 ] == 71 ) &&
(signatureBuffer[4 ] == 13 ) &&
(signatureBuffer[5 ] == 10 ) &&
(signatureBuffer[6 ] == 26 ) &&
(signatureBuffer[7 ] == 10 )) {
return true ;
}
return false ;
}
private Dimension readGIFDimension(InputStream is) throws IOException {
byte buf [];
is.read(new byte [3 ]); // GIF version
is.read(buf = new byte [2 ]); // width
int widthBuf[] = parseUnsigned(buf);
int width = (widthBuf[1 ] << 8 ) + widthBuf[0 ];
is.read(buf = new byte [2 ]); // height
int heightBuf[] = parseUnsigned(buf);
int height = (heightBuf[1 ] << 8 ) + heightBuf[0 ];
return new Dimension(width, height);
}
private Dimension readPNGDimension(InputStream is) throws IOException {
byte buf[];
is.read(new byte [4 ]); // length
is.read(new byte [4 ]); // type
is.read(buf = new byte [4 ]); // width
int widthBuf[] = parseUnsigned(buf);
int width = (widthBuf[0 ] << 24 ) + (widthBuf[1 ] << 16 ) + (widthBuf[2 ] << 8 ) + widthBuf[3 ];
is.read(buf = new byte [4 ]); // height
int heightBuf[] = parseUnsigned(buf);
int height = (heightBuf[0 ] << 24 ) + (heightBuf[1 ] << 16 ) + (heightBuf[2 ] << 8 ) + heightBuf[3 ];
return new Dimension(width, height);
}
private static int [] parseUnsigned(byte [] src) {
int [] val = new int [src.length];
for (int i = 0 ; i < src.length; i ++) {
val[i] = (src[i] < 0 ) && (src[i] >= -128 ) ? 256 + src[i] : src[i];
}
return val;
}
// -------------------------------------------------------------------------
// public static void main(String[] args) {
// File buildFile = new File("e:/development/projects/CopyIcons/testscript.xml");
// Project p = new Project();
// p.setUserProperty("ant.file", buildFile.getAbsolutePath());
// p.init();
// ProjectHelper helper = ProjectHelper.getProjectHelper();
// p.addReference("ant.projectHelper", helper);
// helper.parse(p, buildFile);
// p.executeTarget(p.getDefaultTarget());
// }
// -------------------------------------------------------------------------
private static class ImageInfo {
public static final int GIF = 1 ;
public static final int PNG = 2 ;
private Dimension dim;
private int type;
private String path;
private String ext;
public ImageInfo(Dimension dm, int tp) {
this (null , dm, tp);
}
public ImageInfo(String pth, Dimension dm, int tp) {
path = pth;
dim = dm;
type = tp;
}
public String getPath() {
return path;
}
public void setPath(String pth) {
path = pth;
}
public int getHeight() {
return dim.height;
}
public int getWidth() {
return dim.width;
}
public String getType() {
if (type == GIF) {
return "GIF" ;
} else if (type == PNG) {
return "PNG" ;
}
return "" ;
}
public String getExt() {
return ext;
}
public String setExt(String ex) {
return ext = ex;
}
}
private static class ProjectIconInfo {
public String prjPath;
public List<ImageInfo> matchingIcons;
public List<ImageInfo> notmatchingIcons;
public ProjectIconInfo(String pth, List<ImageInfo> mi, List<ImageInfo> nmi) {
prjPath = pth;
matchingIcons = mi;
notmatchingIcons = nmi;
}
}
// -------------------------------------------------------------------------
private void dumpListToHTML(List<ProjectIconInfo> lst) {
File reportFile = new File(destDir, "index.html" );
FileOutputStream fos = null ;
try {
fos = new FileOutputStream(reportFile);
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
try (PrintWriter pw = new PrintWriter(new BufferedOutputStream(fos))) {
pw.println("<html>" );
pw.println("<head>" );
pw.println("<style type=\" text/css\">\nbody { font-family: Tahoma, Verdana, sans-serif }\n</style>" );
pw.println("</head>" );
pw.println("<body>" );
pw.println("<h2>List of icons in NetBeans projects</h2>" );
pw.println("<h3>NetBeans Source Root: " + baseDir + "<br/>" );
pw.println("Destination Directory: " + destDir + "</h3>" );
pw.println("<p style=\" width: 70 %\"><b>Description:</b><br/> New Image is image in the Destination Directory, Orig. Image is image in NetBeans Source Root. " +
"By replacing the image in Destination Directory under coresponding module and path you can prepare rebranded " +
"icons in paralel directory structure and then copy them over to NetBeans Source Root. Orig. Image is " +
"in the table just for comparison and reference what image was already changed.</p>" );
for (Iterator<ProjectIconInfo> iter = prjIconInfoList.iterator(); iter.hasNext(); ) {
ProjectIconInfo info = iter.next();
if (!showEmpty && info.matchingIcons.size() == 0 ) {
continue ;
}
pw.println("<p>Module name: <b>" + info.prjPath + "</b></p>" );
pw.println("<p style=\" margin-left: 20 px\">" );
if (info.matchingIcons.size() == 0 ) {
pw.println("<i>--- No icons ---</i>" );
pw.println("</p>" );
continue ;
}
pw.println("<table width=\" 80 %\"border=\" 1 \" cellpadding=\" 3 \" cellspacing=\" 0 \">" );
pw.println("<tr><td><b>Resource Path</b></td>" +
"<td align=\" center\"><b> New Image </b></td>" +
"<td align=\" center\"><b> Orig. image </b></td>" +
"<td align=\" center\"><b> W x H </b></td>" +
"<td align=\" center\"><b> Extension </b></td>" +
"<td align=\" center\"><b> Real Type </b></td></tr>" );
for (Iterator<ImageInfo> goodIter = info.matchingIcons.iterator(); goodIter.hasNext(); ) {
ImageInfo goodInfo = goodIter.next();
String iconPath = goodInfo.getPath();
String copiedIconPath = info.prjPath + File.separator + iconPath;
String originalIconPath = baseDir.getAbsolutePath() + File.separator + info.prjPath + File.separator + iconPath;
pw.println("<tr>" );
pw.println("<td>" );
pw.println("<a href=\" " + copiedIconPath + " \">" + iconPath + "</a>" );
pw.println("</td>" );
pw.println("<td align=\" center\">" );
pw.println("<img src=\" " + copiedIconPath + " \"/>" ); // copied image
pw.println("</td>" );
pw.println("<td align=\" center\">" );
pw.println("<img src=\" file://" + originalIconPath + "\"/>"); // original image
pw.println("</td>" );
pw.println("<td align=\" center\">" + goodInfo.getWidth() + " x " + goodInfo.getHeight() + "</td>" );
pw.println("<td align=\" center\">" + goodInfo.getExt().toUpperCase() + "</td>" );
if (!goodInfo.getExt().equalsIgnoreCase(goodInfo.getType())) {
pw.println("<td align=\" center\"><font color=\" Orange\">" + goodInfo.getType() + "</font></td>" );
} else {
pw.println("<td align=\" center\">" + goodInfo.getType() + "</td>" );
}
pw.println("</tr>" );
}
pw.println("</table>" );
pw.println("</p>" );
}
pw.println("</body>" );
pw.println("</html>" );
pw.flush();
}
log("---> Report was written to file: " + reportFile.getAbsolutePath());
}
private void copyToDestDir(List<ProjectIconInfo> prjInfoList) {
FileSet fs = null ;
for (Iterator<ProjectIconInfo> iter = prjInfoList.iterator(); iter.hasNext(); ) {
fs = new FileSet();
log("Setting basedir for fileset: " + baseDir, Project.MSG_VERBOSE);
ProjectIconInfo prjIconInfo = iter.next();
fs.setDir(new File(baseDir, prjIconInfo.prjPath));
int numFilesToCopy = prjIconInfo.matchingIcons.size() + prjIconInfo.notmatchingIcons.size();
for (Iterator<ImageInfo> matchInfoIter = prjIconInfo.matchingIcons.iterator(); matchInfoIter.hasNext(); ) {
ImageInfo info = matchInfoIter.next();
log("Adding file to matching fileset: " + info.getPath(), Project.MSG_VERBOSE);
fs.setIncludes(info.getPath());
}
for (Iterator<ImageInfo> notmatchInfoIter = prjIconInfo.notmatchingIcons.iterator(); notmatchInfoIter.hasNext(); ) {
ImageInfo info = notmatchInfoIter.next();
log("Adding file to notmatching fileset: " + info.getPath(), Project.MSG_VERBOSE);
fs.setIncludes(info.getPath());
}
if (numFilesToCopy > 0 ) {
Copy copy = (Copy) getProject().createTask("copy" );
copy.addFileset(fs);
File dest = new File(destDir, prjIconInfo.prjPath);
dest.mkdir();
copy.setTodir(dest);
copy.init();
copy.setLocation(getLocation());
copy.execute();
}
}
}
// -------------------------------------------------------------------------
private void scanForProjectDirs(File fl) {
if (depth > userDepth) return ;
//if (isProjectDir(fl)) {
// projectDirList.add(fl);
//}
File allFiles[] = fl.listFiles(new FileFilter() {
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return true ;
}
return false ;
}
});
depth++;
for (File f : allFiles) {
if (isProjectDir(f)) {
// here could be some project exclusion logic
projectDirList.add(f);
log(f.toString(), Project.MSG_VERBOSE);
scanForProjectDirs(f);
} else {
scanForProjectDirs(f);
}
}
depth--;
}
private boolean isProjectDir(File fl) {
File prjDirs[] = fl.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
if ("nbproject" .equals(name)) {
return true ;
}
return false ;
}
});
if (prjDirs.length != 1 ) {
return false ;
}
String prjFiles[] = prjDirs[0 ].list(new FilenameFilter() {
public boolean accept(File dir, String name) {
if ("project.xml" .equals(name)) {
return true ;
}
return false ;
}
});
if (prjFiles.length != 1 ) {
return false ;
}
return true ;
}
private void processProjectDir(File f) {
String prjPath = null ;
//if (f.getAbsolutePath().equals(baseDir.getAbsolutePath())) {
// prjPath = "";
//} else {
prjPath = f.getAbsolutePath().substring(baseDir.getAbsolutePath().length() + 1 );
//}
log("Processing project dir: " + prjPath);
DirectoryScanner ds = new DirectoryScanner();
ds.setBasedir(f);
ds.setIncludes(getAsArray(iconIncludes));
ds.setExcludes(getAsArray(iconExcludes));
ds.setCaseSensitive(false );
ds.scan();
String[] files = ds.getIncludedFiles();
log(" Found " + files.length + " files in " + f);
List<ImageInfo> goodIcons = new ArrayList<>();
List<ImageInfo> badIcons = new ArrayList<>();
for (String file : files) {
String ext = file.substring(file.lastIndexOf('.' ) + 1 );
if (ext.equalsIgnoreCase("gif" ) || ext.equalsIgnoreCase("png" )) {
File iconFile = new File(f, file);
try {
ImageInfo imageInfo = null ;
imageInfo = readImageInfo(iconFile);
if (imageInfo != null ) {
imageInfo.setPath(file);
imageInfo.setExt(ext);
int w = imageInfo.getWidth();
int h = imageInfo.getHeight();
if ((w == 8 && h == 8 ) || (w == 16 && h == 16 ) ||
(w == 24 && h == 24 ) || (w == 32 && h == 32 )) {
goodIcons.add(imageInfo);
} else {
badIcons.add(imageInfo);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
ProjectIconInfo prjIconInfo = new ProjectIconInfo(prjPath, goodIcons, badIcons);
prjIconInfoList.add(prjIconInfo);
}
private String[] getAsArray(String s) {
List<String> list = new ArrayList<>();
for (StringTokenizer stok = new StringTokenizer(s, "," ); stok.hasMoreTokens(); ) {
String token = stok.nextToken().trim();
list.add(token);
}
return list.toArray(new String[list.size()]);
}
}
Messung V0.5 in Prozent C=93 H=94 G=93
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland