1/*
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.codemodel.internal.writer;
27
28import java.io.File;
29import java.io.FileOutputStream;
30import java.io.IOException;
31import java.io.OutputStream;
32import java.util.HashSet;
33import java.util.Set;
34
35import com.sun.codemodel.internal.CodeWriter;
36import com.sun.codemodel.internal.JPackage;
37
38/**
39 * Writes all the source files under the specified file folder.
40 *
41 * @author
42 *      Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
43 */
44public class FileCodeWriter extends CodeWriter {
45
46    /** The target directory to put source code. */
47    private final File target;
48
49    /** specify whether or not to mark the generated files read-only */
50    private final boolean readOnly;
51
52    /** Files that shall be marked as read only. */
53    private final Set<File> readonlyFiles = new HashSet<>();
54
55    public FileCodeWriter( File target ) throws IOException {
56        this(target,false);
57    }
58
59    public FileCodeWriter( File target, String encoding ) throws IOException {
60        this(target,false, encoding);
61    }
62
63    public FileCodeWriter( File target, boolean readOnly ) throws IOException {
64        this(target, readOnly, null);
65    }
66
67    public FileCodeWriter( File target, boolean readOnly, String encoding ) throws IOException {
68        this.target = target;
69        this.readOnly = readOnly;
70        this.encoding = encoding;
71        if(!target.exists() || !target.isDirectory())
72            throw new IOException(target + ": non-existent directory");
73    }
74
75    @Override
76    public OutputStream openBinary(JPackage pkg, String fileName) throws IOException {
77        return new FileOutputStream(getFile(pkg,fileName));
78    }
79
80    protected File getFile(JPackage pkg, String fileName ) throws IOException {
81        File dir;
82        if(pkg == null || pkg.isUnnamed())
83            dir = target;
84        else
85            dir = new File(target, toDirName(pkg));
86
87        if(!dir.exists())   dir.mkdirs();
88
89        File fn = new File(dir,fileName);
90
91        if (fn.exists()) {
92            if (!fn.delete())
93                throw new IOException(fn + ": Can't delete previous version");
94        }
95
96
97        if(readOnly)        readonlyFiles.add(fn);
98        return fn;
99    }
100
101    @Override
102    public void close() throws IOException {
103        // mark files as read-onnly if necessary
104        for (File f : readonlyFiles)
105            f.setReadOnly();
106    }
107
108    /** Converts a package name to the directory name. */
109    private static String toDirName( JPackage pkg ) {
110        return pkg.name().replace('.',File.separatorChar);
111    }
112
113}
114