aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java
blob: a019c13f49d2365a76dac22f53a4553d4fea934d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
 * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
 *
 * Copyright @ 2015 Atlassian Pty Ltd
 *
 * Licensed 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 net.java.sip.communicator.impl.configuration;

import com.sun.jna.*;

import net.java.sip.communicator.util.ServiceUtils;

import org.jitsi.service.configuration.*;
import org.jitsi.service.fileaccess.*;
import org.jitsi.service.libjitsi.*;
import org.jitsi.util.*;
import org.osgi.framework.*;

import java.io.*;

/**
 *
 * @author Emil Ivov
 * @author Lyubomir Marinov
 */
public class ConfigurationActivator
    implements BundleActivator
{
    /**
     * The <tt>Logger</tt> used by the <tt>ConfigurationActivator</tt> class
     * for logging output.
     */
    private static final Logger logger
        = Logger.getLogger(ConfigurationActivator.class);

    /**
     * The currently registered {@link ConfigurationService} instance.
     */
    private ConfigurationService cs;

    /**
     * Starts the configuration service
     *
     * @param bundleContext the <tt>BundleContext</tt> as provided by the OSGi
     * framework.
     * @throws Exception if anything goes wrong
     */
    public void start(BundleContext bundleContext)
        throws Exception
    {
        FileAccessService fas
            = ServiceUtils.getService(bundleContext, FileAccessService.class);

        if (fas != null)
        {
            File usePropFileConfig;
            try
            {
                usePropFileConfig
                    = fas.getPrivatePersistentFile(
                            ".usepropfileconfig",
                            FileCategory.PROFILE);
            }
            catch (Exception ise)
            {
                // There is somewhat of a chicken-and-egg dependency between
                // FileConfigurationServiceImpl and ConfigurationServiceImpl:
                // FileConfigurationServiceImpl throws IllegalStateException if
                // certain System properties are not set,
                // ConfigurationServiceImpl will make sure that these properties
                // are set but it will do that later.
                // A SecurityException is thrown when the destination
                // is not writable or we do not have access to that folder
                usePropFileConfig = null;
            }

            if (usePropFileConfig != null && usePropFileConfig.exists())
            {
                logger.info("Using properties file configuration store.");
                this.cs = LibJitsi.getConfigurationService();
            }
        }

        if (this.cs == null)
        {
            this.cs = new JdbcConfigService(fas);
        }

        bundleContext.registerService(
                ConfigurationService.class.getName(),
                this.cs,
                null);

        fixPermissions(this.cs);
    }

    /**
     * Causes the configuration service to store the properties object and
     * unregisters the configuration service.
     *
     * @param bundleContext <tt>BundleContext</tt>
     * @throws Exception if anything goes wrong while storing the properties
     * managed by the <tt>ConfigurationService</tt> implementation provided by
     * this bundle and while unregistering the service in question
     */
    public void stop(BundleContext bundleContext)
        throws Exception
    {
        this.cs.storeConfiguration();
        this.cs = null;
    }

    /**
     * Makes home folder and the configuration file readable and writable only
     * to the owner.
     *
     * @param cs the <tt>ConfigurationService</tt> instance to check for home
     * folder and configuration file.
     */
    private static void fixPermissions(ConfigurationService cs)
    {
        if(!OSUtils.IS_LINUX && !OSUtils.IS_MAC)
            return;

        try
        {
            // let's check config file and config folder
            File homeFolder
                = new File(cs.getScHomeDirLocation(), cs.getScHomeDirName());
            CLibrary  libc = (CLibrary) Native.loadLibrary("c", CLibrary.class);

            libc.chmod(homeFolder.getAbsolutePath(), 0700);

            String fileName = cs.getConfigurationFilename();

            if(fileName != null)
            {
                File cf = new File(homeFolder, fileName);
                if(cf.exists())
                    libc.chmod(cf.getAbsolutePath(), 0600);
            }
        }
        catch(Throwable t)
        {
            logger.error(
                    "Error creating c lib instance for fixing file permissions",
                    t);

            if (t instanceof InterruptedException)
                Thread.currentThread().interrupt();
            else if (t instanceof ThreadDeath)
                throw (ThreadDeath) t;
        }
    }

    /**
     * The JNA interface to the <tt>c</tt> library and the <tt>chmod</tt>
     * function we use to fix permissions of user files and folders.
     */
    public interface CLibrary
        extends Library
    {
        /**
         * Changes file permissions.
         *
         * @param path the path to the file or folder the permissions of which
         * are to be changed.
         * @param mode the mode operand
         * @return <tt>0</tt> upon successful completion; otherwise,
         * <tt>-1</tt>. If <tt>-1</tt> is returned, no change to the file mode
         * occurs.
         */
        public int chmod(String path, int mode);
    }
}